Skip to content

Commit c9dc1a0

Browse files
committed
DATAJDBC-188 - Ensure proper behavior of delete logic.
No behavior changed. Added tests on various levels for deleting entities with references to other entities.
1 parent 71a4861 commit c9dc1a0

File tree

4 files changed

+179
-7
lines changed

4 files changed

+179
-7
lines changed

src/main/java/org/springframework/data/jdbc/mapping/model/JdbcMappingContext.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,13 @@ public void setSimpleTypeHolder(SimpleTypeHolder simpleTypes) {
8080
this.simpleTypeHolder = simpleTypes;
8181
}
8282

83+
/**
84+
* returns all {@link PropertyPath}s reachable from the root type.
85+
*
86+
* @param rootType
87+
* @param path
88+
* @return
89+
*/
8390
public List<PropertyPath> referencedEntities(Class<?> rootType, PropertyPath path) {
8491

8592
List<PropertyPath> paths = new ArrayList<>();

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

Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import org.springframework.data.annotation.Id;
2828
import org.springframework.data.jdbc.core.conversion.AggregateChange.Kind;
2929
import org.springframework.data.jdbc.core.conversion.DbAction.Delete;
30+
import org.springframework.data.jdbc.core.conversion.DbAction.DeleteAll;
3031
import org.springframework.data.jdbc.mapping.model.JdbcMappingContext;
3132
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations;
3233

@@ -38,22 +39,49 @@
3839
@RunWith(MockitoJUnitRunner.class)
3940
public class JdbcEntityDeleteWriterUnitTests {
4041

41-
JdbcEntityDeleteWriter converter = new JdbcEntityDeleteWriter(new JdbcMappingContext(mock(NamedParameterJdbcOperations.class)));
42+
JdbcEntityDeleteWriter converter = new JdbcEntityDeleteWriter(
43+
new JdbcMappingContext(mock(NamedParameterJdbcOperations.class)));
4244

43-
@Test
45+
private static Object dotPath(DbAction dba) {
46+
47+
JdbcPropertyPath propertyPath = dba.getPropertyPath();
48+
49+
return propertyPath == null ? null : propertyPath.toDotPath();
50+
}
51+
52+
@Test // DATAJDBC-112
4453
public void deleteDeletesTheEntityAndReferencedEntities() {
4554

4655
SomeEntity entity = new SomeEntity(23L);
4756

4857
AggregateChange<SomeEntity> aggregateChange = new AggregateChange(Kind.DELETE, SomeEntity.class, entity);
4958

50-
converter.write(entity, aggregateChange);
59+
converter.write(entity.id, aggregateChange);
60+
61+
Assertions.assertThat(aggregateChange.getActions())
62+
.extracting(DbAction::getClass, DbAction::getEntityType, JdbcEntityDeleteWriterUnitTests::dotPath) //
63+
.containsExactly( //
64+
Tuple.tuple(Delete.class, YetAnother.class, "other.yetAnother"), //
65+
Tuple.tuple(Delete.class, OtherEntity.class, "other"), //
66+
Tuple.tuple(Delete.class, SomeEntity.class, null) //
67+
);
68+
}
69+
70+
@Test // DATAJDBC-188
71+
public void deleteAllDeletesAllEntitiesAndReferencedEntities() {
72+
73+
SomeEntity entity = new SomeEntity(23L);
74+
75+
AggregateChange<SomeEntity> aggregateChange = new AggregateChange(Kind.DELETE, SomeEntity.class, null);
76+
77+
converter.write(null, aggregateChange);
5178

52-
Assertions.assertThat(aggregateChange.getActions()).extracting(DbAction::getClass, DbAction::getEntityType)
79+
Assertions.assertThat(aggregateChange.getActions())
80+
.extracting(DbAction::getClass, DbAction::getEntityType, JdbcEntityDeleteWriterUnitTests::dotPath) //
5381
.containsExactly( //
54-
Tuple.tuple(Delete.class, YetAnother.class), //
55-
Tuple.tuple(Delete.class, OtherEntity.class), //
56-
Tuple.tuple(Delete.class, SomeEntity.class) //
82+
Tuple.tuple(DeleteAll.class, YetAnother.class, "other.yetAnother"), //
83+
Tuple.tuple(DeleteAll.class, OtherEntity.class, "other"), //
84+
Tuple.tuple(DeleteAll.class, SomeEntity.class, null) //
5785
);
5886
}
5987

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

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
import org.springframework.data.annotation.Id;
3434
import org.springframework.data.jdbc.core.conversion.AggregateChange.Kind;
3535
import org.springframework.data.jdbc.core.conversion.DbAction.Delete;
36+
import org.springframework.data.jdbc.core.conversion.DbAction.DeleteAll;
3637
import org.springframework.data.jdbc.core.conversion.DbAction.Insert;
3738
import org.springframework.data.jdbc.core.conversion.DbAction.Update;
3839
import org.springframework.data.jdbc.mapping.model.JdbcMappingContext;
@@ -165,6 +166,39 @@ public void cascadingReferencesTriggerCascadingActions() {
165166
);
166167
}
167168

169+
@Test // DATAJDBC-188
170+
public void cascadingReferencesTriggerCascadingActionsForUpdate() {
171+
172+
CascadingReferenceEntity entity = new CascadingReferenceEntity(23L);
173+
174+
entity.other.add(createMiddleElement( //
175+
new Element(null), //
176+
new Element(null)) //
177+
);
178+
179+
entity.other.add(createMiddleElement( //
180+
new Element(null), //
181+
new Element(null)) //
182+
);
183+
184+
AggregateChange<SingleReferenceEntity> aggregateChange = new AggregateChange(Kind.SAVE, CascadingReferenceEntity.class, entity);
185+
186+
converter.write(entity, aggregateChange);
187+
188+
assertThat(aggregateChange.getActions()).extracting(DbAction::getClass, DbAction::getEntityType, this::extractPath) //
189+
.containsExactly( //
190+
tuple(Delete.class, Element.class, "other.element"),
191+
tuple(Delete.class, CascadingReferenceMiddleElement.class, "other"),
192+
tuple(Update.class, CascadingReferenceEntity.class, ""), //
193+
tuple(Insert.class, CascadingReferenceMiddleElement.class, "other"), //
194+
tuple(Insert.class, Element.class, "other.element"), //
195+
tuple(Insert.class, Element.class, "other.element"), //
196+
tuple(Insert.class, CascadingReferenceMiddleElement.class, "other"), //
197+
tuple(Insert.class, Element.class, "other.element"), //
198+
tuple(Insert.class, Element.class, "other.element") //
199+
);
200+
}
201+
168202
@Test // DATAJDBC-131
169203
public void newEntityWithEmptyMapResultsInSingleInsert() {
170204

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
/*
2+
* Copyright 2018 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.data.jdbc.mapping.model;
17+
18+
import org.junit.Test;
19+
import org.springframework.data.mapping.PropertyPath;
20+
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations;
21+
22+
import java.util.List;
23+
import java.util.Map;
24+
import java.util.Set;
25+
26+
import static org.assertj.core.api.Assertions.assertThat;
27+
import static org.mockito.Mockito.mock;
28+
29+
/**
30+
* @author Jens Schauder
31+
*/
32+
public class JdbcMappingContextUnitTests {
33+
34+
JdbcMappingContext context = new JdbcMappingContext(mock(NamedParameterJdbcOperations.class));
35+
36+
// DATAJDBC-188
37+
@Test
38+
public void simpleEntityDoesntReferenceOtherEntities() {
39+
40+
List<PropertyPath> paths = context.referencedEntities(SimpleEntity.class, null);
41+
42+
assertThat(paths).isEmpty();
43+
}
44+
45+
// DATAJDBC-188
46+
@Test
47+
public void cascadingReferencesGetFound() {
48+
49+
List<PropertyPath> paths = context.referencedEntities(CascadingEntity.class, null);
50+
51+
assertThat(paths).extracting(PropertyPath::toDotPath) //
52+
.containsExactly( //
53+
"reference.reference", //
54+
"reference" //
55+
) ;
56+
}
57+
58+
// DATAJDBC-188
59+
@Test
60+
public void setReferencesGetFound() {
61+
62+
List<PropertyPath> paths = context.referencedEntities(EntityWithSet.class, null);
63+
64+
assertThat(paths).extracting(PropertyPath::toDotPath) //
65+
.containsExactly( //
66+
"set.reference", //
67+
"set" //
68+
) ;
69+
}
70+
71+
// DATAJDBC-188
72+
@Test
73+
public void mapReferencesGetFound() {
74+
75+
List<PropertyPath> paths = context.referencedEntities(EntityWithMap.class, null);
76+
77+
assertThat(paths).extracting(PropertyPath::toDotPath) //
78+
.containsExactly( //
79+
"map.reference", //
80+
"map" //
81+
) ;
82+
}
83+
84+
private static class SimpleEntity {
85+
String name;
86+
}
87+
88+
private static class CascadingEntity {
89+
MiddleEntity reference;
90+
}
91+
92+
private static class MiddleEntity {
93+
SimpleEntity reference;
94+
}
95+
96+
private static class EntityWithMap {
97+
Map<String, MiddleEntity> map;
98+
}
99+
100+
private static class EntityWithSet {
101+
Set<MiddleEntity> set;
102+
}
103+
}

0 commit comments

Comments
 (0)