diff --git a/pom.xml b/pom.xml
index 87b7e95ebe..109046e2ef 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,7 +5,7 @@
org.springframework.data
spring-data-relational-parent
- 1.2.0.BUILD-SNAPSHOT
+ 1.2.0.DATAJDBC-417-SNAPSHOT
pom
Spring Data Relational Parent
diff --git a/spring-data-jdbc-distribution/pom.xml b/spring-data-jdbc-distribution/pom.xml
index f2bbb72319..8e1d83721c 100644
--- a/spring-data-jdbc-distribution/pom.xml
+++ b/spring-data-jdbc-distribution/pom.xml
@@ -14,7 +14,7 @@
org.springframework.data
spring-data-relational-parent
- 1.2.0.BUILD-SNAPSHOT
+ 1.2.0.DATAJDBC-417-SNAPSHOT
../pom.xml
diff --git a/spring-data-jdbc/pom.xml b/spring-data-jdbc/pom.xml
index 0904eb8136..c476e012aa 100644
--- a/spring-data-jdbc/pom.xml
+++ b/spring-data-jdbc/pom.xml
@@ -5,7 +5,7 @@
4.0.0
spring-data-jdbc
- 1.2.0.BUILD-SNAPSHOT
+ 1.2.0.DATAJDBC-417-SNAPSHOT
Spring Data JDBC
Spring Data module for JDBC repositories.
@@ -14,7 +14,7 @@
org.springframework.data
spring-data-relational-parent
- 1.2.0.BUILD-SNAPSHOT
+ 1.2.0.DATAJDBC-417-SNAPSHOT
diff --git a/spring-data-relational/pom.xml b/spring-data-relational/pom.xml
index 1751c4244e..bc932dabf3 100644
--- a/spring-data-relational/pom.xml
+++ b/spring-data-relational/pom.xml
@@ -5,7 +5,7 @@
4.0.0
spring-data-relational
- 1.2.0.BUILD-SNAPSHOT
+ 1.2.0.DATAJDBC-417-SNAPSHOT
Spring Data Relational
Spring Data Relational support
@@ -13,7 +13,7 @@
org.springframework.data
spring-data-relational-parent
- 1.2.0.BUILD-SNAPSHOT
+ 1.2.0.DATAJDBC-417-SNAPSHOT
diff --git a/spring-data-relational/src/main/java/org/springframework/data/relational/core/conversion/WritingContext.java b/spring-data-relational/src/main/java/org/springframework/data/relational/core/conversion/WritingContext.java
index faca7bd195..ece16ad044 100644
--- a/spring-data-relational/src/main/java/org/springframework/data/relational/core/conversion/WritingContext.java
+++ b/spring-data-relational/src/main/java/org/springframework/data/relational/core/conversion/WritingContext.java
@@ -202,7 +202,8 @@ private List from(PersistentPropertyPath
} else {
- List pathNodes = nodesCache.get(path.getParentPath());
+ List pathNodes = nodesCache.getOrDefault(path.getParentPath(), Collections.emptyList());
+
pathNodes.forEach(parentNode -> {
// todo: this should go into pathnode
@@ -238,7 +239,17 @@ private boolean isDirectlyReferencedByRootIgnoringEmbeddables(
@Nullable
private Object getFromRootValue(PersistentPropertyPath path) {
- return path.getBaseProperty().getOwner().getPropertyAccessor(entity).getProperty(path);
+
+ if (path.getLength() == 0)
+ return entity;
+
+ Object parent = getFromRootValue(path.getParentPath());
+ if (parent == null) {
+ return null;
+ }
+
+ return context.getRequiredPersistentEntity(parent.getClass()).getPropertyAccessor(parent)
+ .getProperty(path.getRequiredLeafProperty());
}
private List createNodes(PersistentPropertyPath path,
diff --git a/spring-data-relational/src/test/java/org/springframework/data/relational/core/conversion/RelationalEntityWriterUnitTests.java b/spring-data-relational/src/test/java/org/springframework/data/relational/core/conversion/RelationalEntityWriterUnitTests.java
index 3bf93eb38d..d66044d7d4 100644
--- a/spring-data-relational/src/test/java/org/springframework/data/relational/core/conversion/RelationalEntityWriterUnitTests.java
+++ b/spring-data-relational/src/test/java/org/springframework/data/relational/core/conversion/RelationalEntityWriterUnitTests.java
@@ -29,7 +29,6 @@
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.junit.MockitoJUnitRunner;
-
import org.springframework.data.annotation.Id;
import org.springframework.data.mapping.PersistentPropertyPath;
import org.springframework.data.mapping.PersistentPropertyPaths;
@@ -118,6 +117,7 @@ public void newEntityGetsConvertedToOneInsertByEmbeddedEntities() {
);
}
+
@Test // DATAJDBC-112
public void newEntityWithReferenceGetsConvertedToTwoInserts() {
@@ -530,6 +530,51 @@ public void multiLevelQualifiedReferencesWithOutId() {
);
}
+ @Test // DATAJDBC-417
+ public void savingANullEmbeddedWithEntity() {
+
+ EmbeddedReferenceChainEntity entity = new EmbeddedReferenceChainEntity(null);
+ // the embedded is null !!!
+
+ AggregateChange aggregateChange = //
+ new AggregateChange<>(Kind.SAVE, EmbeddedReferenceChainEntity.class, entity);
+
+ converter.write(entity, aggregateChange);
+
+ assertThat(aggregateChange.getActions()) //
+ .extracting(DbAction::getClass, //
+ DbAction::getEntityType, //
+ DbActionTestSupport::extractPath, //
+ DbActionTestSupport::actualEntityType, //
+ DbActionTestSupport::isWithDependsOn) //
+ .containsExactly( //
+ tuple(InsertRoot.class, EmbeddedReferenceChainEntity.class, "", EmbeddedReferenceChainEntity.class, false) //
+ );
+ }
+ @Test // DATAJDBC-417
+ public void savingInnerNullEmbeddedWithEntity() {
+
+ RootWithEmbeddedReferenceChainEntity root = new RootWithEmbeddedReferenceChainEntity(null);
+ root.other = new EmbeddedReferenceChainEntity(null);
+ // the embedded is null !!!
+
+ AggregateChange aggregateChange = //
+ new AggregateChange<>(Kind.SAVE, RootWithEmbeddedReferenceChainEntity.class, root);
+
+ converter.write(root, aggregateChange);
+
+ assertThat(aggregateChange.getActions()) //
+ .extracting(DbAction::getClass, //
+ DbAction::getEntityType, //
+ DbActionTestSupport::extractPath, //
+ DbActionTestSupport::actualEntityType, //
+ DbActionTestSupport::isWithDependsOn) //
+ .containsExactly( //
+ tuple(InsertRoot.class, RootWithEmbeddedReferenceChainEntity.class, "", RootWithEmbeddedReferenceChainEntity.class, false), //
+ tuple(Insert.class, EmbeddedReferenceChainEntity.class, "other", EmbeddedReferenceChainEntity.class, true) //
+ );
+ }
+
private CascadingReferenceMiddleElement createMiddleElement(Element first, Element second) {
CascadingReferenceMiddleElement middleElement1 = new CascadingReferenceMiddleElement(null);
@@ -560,13 +605,6 @@ private Object getQualifier(DbAction a, PersistentPropertyPath path) {
-
- return a instanceof DbAction.WithDependingOn //
- ? ((DbAction.WithDependingOn) a).getQualifiers().size() //
- : 0;
- }
-
static PersistentPropertyPath toPath(String path, Class source,
RelationalMappingContext context) {
@@ -592,6 +630,19 @@ static class EmbeddedReferenceEntity {
@Embedded(onEmpty = OnEmpty.USE_NULL, prefix = "prefix_") Element other;
}
+ @RequiredArgsConstructor
+ static class EmbeddedReferenceChainEntity {
+
+ @Id final Long id;
+ @Embedded(onEmpty = OnEmpty.USE_NULL, prefix = "prefix_") ElementReference other;
+ }
+ @RequiredArgsConstructor
+ static class RootWithEmbeddedReferenceChainEntity {
+
+ @Id final Long id;
+ EmbeddedReferenceChainEntity other;
+ }
+
@RequiredArgsConstructor
static class ReferenceWoIdEntity {
@@ -648,6 +699,11 @@ private static class Element {
@Id final Long id;
}
+ @RequiredArgsConstructor
+ private static class ElementReference {
+ final Element element;
+ }
+
@RequiredArgsConstructor
private static class NoIdListMapContainer {