DATAJDBC-188 - Ensure proper behavior of delete logic.
No behavior changed. Added tests on various levels for deleting entities with references to other entities.
This commit is contained in:
committed by
Greg Turnquist
parent
bd9b1ed301
commit
0460f2f509
@@ -94,6 +94,10 @@ public class JdbcMappingContext extends AbstractMappingContext<JdbcPersistentEnt
|
||||
this.simpleTypeHolder = simpleTypes;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns all {@link PropertyPath}s reachable from the root type in the order needed for deleting, i.e. the deepest
|
||||
* reference first.
|
||||
*/
|
||||
public List<PropertyPath> referencedEntities(Class<?> rootType, PropertyPath path) {
|
||||
|
||||
List<PropertyPath> paths = new ArrayList<>();
|
||||
|
||||
@@ -25,6 +25,7 @@ import org.mockito.junit.MockitoJUnitRunner;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.jdbc.core.conversion.AggregateChange.Kind;
|
||||
import org.springframework.data.jdbc.core.conversion.DbAction.Delete;
|
||||
import org.springframework.data.jdbc.core.conversion.DbAction.DeleteAll;
|
||||
import org.springframework.data.jdbc.core.mapping.JdbcMappingContext;
|
||||
|
||||
/**
|
||||
@@ -37,21 +38,46 @@ public class JdbcEntityDeleteWriterUnitTests {
|
||||
|
||||
JdbcEntityDeleteWriter converter = new JdbcEntityDeleteWriter(new JdbcMappingContext());
|
||||
|
||||
@Test
|
||||
private static Object dotPath(DbAction dba) {
|
||||
|
||||
JdbcPropertyPath propertyPath = dba.getPropertyPath();
|
||||
return propertyPath == null ? null : propertyPath.toDotPath();
|
||||
}
|
||||
|
||||
@Test // DATAJDBC-112
|
||||
public void deleteDeletesTheEntityAndReferencedEntities() {
|
||||
|
||||
SomeEntity entity = new SomeEntity(23L);
|
||||
|
||||
AggregateChange<SomeEntity> aggregateChange = new AggregateChange<>(Kind.DELETE, SomeEntity.class, entity);
|
||||
|
||||
converter.write(entity, aggregateChange);
|
||||
converter.write(entity.id, aggregateChange);
|
||||
|
||||
Assertions.assertThat(aggregateChange.getActions()).extracting(DbAction::getClass, DbAction::getEntityType)
|
||||
Assertions.assertThat(aggregateChange.getActions())
|
||||
.extracting(DbAction::getClass, DbAction::getEntityType, JdbcEntityDeleteWriterUnitTests::dotPath) //
|
||||
.containsExactly( //
|
||||
Tuple.tuple(Delete.class, YetAnother.class), //
|
||||
Tuple.tuple(Delete.class, OtherEntity.class), //
|
||||
Tuple.tuple(Delete.class, SomeEntity.class) //
|
||||
);
|
||||
Tuple.tuple(Delete.class, YetAnother.class, "other.yetAnother"), //
|
||||
Tuple.tuple(Delete.class, OtherEntity.class, "other"), //
|
||||
Tuple.tuple(Delete.class, SomeEntity.class, null) //
|
||||
);
|
||||
}
|
||||
|
||||
@Test // DATAJDBC-188
|
||||
public void deleteAllDeletesAllEntitiesAndReferencedEntities() {
|
||||
|
||||
SomeEntity entity = new SomeEntity(23L);
|
||||
|
||||
AggregateChange<SomeEntity> aggregateChange = new AggregateChange(Kind.DELETE, SomeEntity.class, null);
|
||||
|
||||
converter.write(null, aggregateChange);
|
||||
|
||||
Assertions.assertThat(aggregateChange.getActions())
|
||||
.extracting(DbAction::getClass, DbAction::getEntityType, JdbcEntityDeleteWriterUnitTests::dotPath) //
|
||||
.containsExactly( //
|
||||
Tuple.tuple(DeleteAll.class, YetAnother.class, "other.yetAnother"), //
|
||||
Tuple.tuple(DeleteAll.class, OtherEntity.class, "other"), //
|
||||
Tuple.tuple(DeleteAll.class, SomeEntity.class, null) //
|
||||
);
|
||||
}
|
||||
|
||||
@Data
|
||||
|
||||
@@ -32,6 +32,7 @@ import org.mockito.junit.MockitoJUnitRunner;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.jdbc.core.conversion.AggregateChange.Kind;
|
||||
import org.springframework.data.jdbc.core.conversion.DbAction.Delete;
|
||||
import org.springframework.data.jdbc.core.conversion.DbAction.DeleteAll;
|
||||
import org.springframework.data.jdbc.core.conversion.DbAction.Insert;
|
||||
import org.springframework.data.jdbc.core.conversion.DbAction.Update;
|
||||
import org.springframework.data.jdbc.core.mapping.JdbcMappingContext;
|
||||
@@ -163,6 +164,39 @@ public class JdbcEntityWriterUnitTests {
|
||||
);
|
||||
}
|
||||
|
||||
@Test // DATAJDBC-188
|
||||
public void cascadingReferencesTriggerCascadingActionsForUpdate() {
|
||||
|
||||
CascadingReferenceEntity entity = new CascadingReferenceEntity(23L);
|
||||
|
||||
entity.other.add(createMiddleElement( //
|
||||
new Element(null), //
|
||||
new Element(null)) //
|
||||
);
|
||||
|
||||
entity.other.add(createMiddleElement( //
|
||||
new Element(null), //
|
||||
new Element(null)) //
|
||||
);
|
||||
|
||||
AggregateChange<SingleReferenceEntity> aggregateChange = new AggregateChange(Kind.SAVE, CascadingReferenceEntity.class, entity);
|
||||
|
||||
converter.write(entity, aggregateChange);
|
||||
|
||||
assertThat(aggregateChange.getActions()).extracting(DbAction::getClass, DbAction::getEntityType, this::extractPath) //
|
||||
.containsExactly( //
|
||||
tuple(Delete.class, Element.class, "other.element"),
|
||||
tuple(Delete.class, CascadingReferenceMiddleElement.class, "other"),
|
||||
tuple(Update.class, CascadingReferenceEntity.class, ""), //
|
||||
tuple(Insert.class, CascadingReferenceMiddleElement.class, "other"), //
|
||||
tuple(Insert.class, Element.class, "other.element"), //
|
||||
tuple(Insert.class, Element.class, "other.element"), //
|
||||
tuple(Insert.class, CascadingReferenceMiddleElement.class, "other"), //
|
||||
tuple(Insert.class, Element.class, "other.element"), //
|
||||
tuple(Insert.class, Element.class, "other.element") //
|
||||
);
|
||||
}
|
||||
|
||||
@Test // DATAJDBC-131
|
||||
public void newEntityWithEmptyMapResultsInSingleInsert() {
|
||||
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* Copyright 2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.jdbc.mapping.model;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.data.jdbc.core.mapping.JdbcMappingContext;
|
||||
import org.springframework.data.mapping.PropertyPath;
|
||||
|
||||
/**
|
||||
* @author Jens Schauder
|
||||
*/
|
||||
public class JdbcMappingContextUnitTests {
|
||||
|
||||
JdbcMappingContext context = new JdbcMappingContext();
|
||||
|
||||
// DATAJDBC-188
|
||||
@Test
|
||||
public void simpleEntityDoesntReferenceOtherEntities() {
|
||||
|
||||
List<PropertyPath> paths = context.referencedEntities(SimpleEntity.class, null);
|
||||
|
||||
assertThat(paths).isEmpty();
|
||||
}
|
||||
|
||||
// DATAJDBC-188
|
||||
@Test
|
||||
public void cascadingReferencesGetFound() {
|
||||
|
||||
List<PropertyPath> paths = context.referencedEntities(CascadingEntity.class, null);
|
||||
|
||||
assertThat(paths).extracting(PropertyPath::toDotPath) //
|
||||
.containsExactly( //
|
||||
"reference.reference", //
|
||||
"reference" //
|
||||
);
|
||||
}
|
||||
|
||||
// DATAJDBC-188
|
||||
@Test
|
||||
public void setReferencesGetFound() {
|
||||
|
||||
List<PropertyPath> paths = context.referencedEntities(EntityWithSet.class, null);
|
||||
|
||||
assertThat(paths).extracting(PropertyPath::toDotPath) //
|
||||
.containsExactly( //
|
||||
"set.reference", //
|
||||
"set" //
|
||||
);
|
||||
}
|
||||
|
||||
// DATAJDBC-188
|
||||
@Test
|
||||
public void mapReferencesGetFound() {
|
||||
|
||||
List<PropertyPath> paths = context.referencedEntities(EntityWithMap.class, null);
|
||||
|
||||
assertThat(paths).extracting(PropertyPath::toDotPath) //
|
||||
.containsExactly( //
|
||||
"map.reference", //
|
||||
"map" //
|
||||
);
|
||||
}
|
||||
|
||||
private static class SimpleEntity {
|
||||
String name;
|
||||
}
|
||||
|
||||
private static class CascadingEntity {
|
||||
MiddleEntity reference;
|
||||
}
|
||||
|
||||
private static class MiddleEntity {
|
||||
SimpleEntity reference;
|
||||
}
|
||||
|
||||
private static class EntityWithMap {
|
||||
Map<String, MiddleEntity> map;
|
||||
}
|
||||
|
||||
private static class EntityWithSet {
|
||||
Set<MiddleEntity> set;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user