DATAJDBC-417 - Fixed saving an entity containing a null embeddable with a reference to a further entity.
Constructing the DbActions assumed that the parent of a path exists (i.e. is not null) and created parent nodes. Original pull request: #169.
This commit is contained in:
committed by
Mark Paluch
parent
88dbbbaf41
commit
cf9b480ea2
@@ -202,7 +202,8 @@ class WritingContext {
|
||||
|
||||
} else {
|
||||
|
||||
List<PathNode> pathNodes = nodesCache.get(path.getParentPath());
|
||||
List<PathNode> pathNodes = nodesCache.getOrDefault(path.getParentPath(), Collections.emptyList());
|
||||
|
||||
pathNodes.forEach(parentNode -> {
|
||||
|
||||
// todo: this should go into pathnode
|
||||
@@ -238,7 +239,17 @@ class WritingContext {
|
||||
|
||||
@Nullable
|
||||
private Object getFromRootValue(PersistentPropertyPath<RelationalPersistentProperty> 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<PathNode> createNodes(PersistentPropertyPath<RelationalPersistentProperty> path,
|
||||
|
||||
@@ -29,7 +29,6 @@ import java.util.Set;
|
||||
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 class RelationalEntityWriterUnitTests {
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@Test // DATAJDBC-112
|
||||
public void newEntityWithReferenceGetsConvertedToTwoInserts() {
|
||||
|
||||
@@ -530,6 +530,51 @@ public class RelationalEntityWriterUnitTests {
|
||||
);
|
||||
}
|
||||
|
||||
@Test // DATAJDBC-417
|
||||
public void savingANullEmbeddedWithEntity() {
|
||||
|
||||
EmbeddedReferenceChainEntity entity = new EmbeddedReferenceChainEntity(null);
|
||||
// the embedded is null !!!
|
||||
|
||||
AggregateChange<EmbeddedReferenceChainEntity> 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<RootWithEmbeddedReferenceChainEntity> 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);
|
||||
@@ -585,6 +630,19 @@ public class RelationalEntityWriterUnitTests {
|
||||
@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 {
|
||||
|
||||
@@ -641,6 +699,11 @@ public class RelationalEntityWriterUnitTests {
|
||||
@Id final Long id;
|
||||
}
|
||||
|
||||
@RequiredArgsConstructor
|
||||
private static class ElementReference {
|
||||
final Element element;
|
||||
}
|
||||
|
||||
@RequiredArgsConstructor
|
||||
private static class NoIdListMapContainer {
|
||||
|
||||
|
||||
Reference in New Issue
Block a user