Browse Source

DATAJDBC-188 - Ensure proper behavior of delete logic.

No behavior changed.
Added tests on various levels for deleting entities with references to other entities.
pull/73/head
Jens Schauder 8 years ago committed by Greg Turnquist
parent
commit
0460f2f509
No known key found for this signature in database
GPG Key ID: CB2FA4D512B5C413
  1. 4
      src/main/java/org/springframework/data/jdbc/core/mapping/JdbcMappingContext.java
  2. 38
      src/test/java/org/springframework/data/jdbc/core/conversion/JdbcEntityDeleteWriterUnitTests.java
  3. 34
      src/test/java/org/springframework/data/jdbc/core/conversion/JdbcEntityWriterUnitTests.java
  4. 102
      src/test/java/org/springframework/data/jdbc/mapping/model/JdbcMappingContextUnitTests.java

4
src/main/java/org/springframework/data/jdbc/core/mapping/JdbcMappingContext.java

@ -94,6 +94,10 @@ public class JdbcMappingContext extends AbstractMappingContext<JdbcPersistentEnt @@ -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<>();

38
src/test/java/org/springframework/data/jdbc/core/conversion/JdbcEntityDeleteWriterUnitTests.java

@ -25,6 +25,7 @@ import org.mockito.junit.MockitoJUnitRunner; @@ -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,20 +38,45 @@ public class JdbcEntityDeleteWriterUnitTests { @@ -37,20 +38,45 @@ 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, JdbcEntityDeleteWriterUnitTests::dotPath) //
.containsExactly( //
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)
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(DeleteAll.class, YetAnother.class, "other.yetAnother"), //
Tuple.tuple(DeleteAll.class, OtherEntity.class, "other"), //
Tuple.tuple(DeleteAll.class, SomeEntity.class, null) //
);
}

34
src/test/java/org/springframework/data/jdbc/core/conversion/JdbcEntityWriterUnitTests.java

@ -32,6 +32,7 @@ import org.mockito.junit.MockitoJUnitRunner; @@ -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 { @@ -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() {

102
src/test/java/org/springframework/data/jdbc/mapping/model/JdbcMappingContextUnitTests.java

@ -0,0 +1,102 @@ @@ -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;
}
}
Loading…
Cancel
Save