Skip to content

Commit 0460f2f

Browse files
schaudergregturn
authored andcommitted
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 bd9b1ed commit 0460f2f

File tree

4 files changed

+173
-7
lines changed

4 files changed

+173
-7
lines changed

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,10 @@ public void setSimpleTypeHolder(SimpleTypeHolder simpleTypes) {
9494
this.simpleTypeHolder = simpleTypes;
9595
}
9696

97+
/**
98+
* returns all {@link PropertyPath}s reachable from the root type in the order needed for deleting, i.e. the deepest
99+
* reference first.
100+
*/
97101
public List<PropertyPath> referencedEntities(Class<?> rootType, PropertyPath path) {
98102

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

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

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import org.springframework.data.annotation.Id;
2626
import org.springframework.data.jdbc.core.conversion.AggregateChange.Kind;
2727
import org.springframework.data.jdbc.core.conversion.DbAction.Delete;
28+
import org.springframework.data.jdbc.core.conversion.DbAction.DeleteAll;
2829
import org.springframework.data.jdbc.core.mapping.JdbcMappingContext;
2930

3031
/**
@@ -37,21 +38,46 @@ public class JdbcEntityDeleteWriterUnitTests {
3738

3839
JdbcEntityDeleteWriter converter = new JdbcEntityDeleteWriter(new JdbcMappingContext());
3940

40-
@Test
41+
private static Object dotPath(DbAction dba) {
42+
43+
JdbcPropertyPath propertyPath = dba.getPropertyPath();
44+
return propertyPath == null ? null : propertyPath.toDotPath();
45+
}
46+
47+
@Test // DATAJDBC-112
4148
public void deleteDeletesTheEntityAndReferencedEntities() {
4249

4350
SomeEntity entity = new SomeEntity(23L);
4451

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

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

49-
Assertions.assertThat(aggregateChange.getActions()).extracting(DbAction::getClass, DbAction::getEntityType)
74+
Assertions.assertThat(aggregateChange.getActions())
75+
.extracting(DbAction::getClass, DbAction::getEntityType, JdbcEntityDeleteWriterUnitTests::dotPath) //
5076
.containsExactly( //
51-
Tuple.tuple(Delete.class, YetAnother.class), //
52-
Tuple.tuple(Delete.class, OtherEntity.class), //
53-
Tuple.tuple(Delete.class, SomeEntity.class) //
54-
);
77+
Tuple.tuple(DeleteAll.class, YetAnother.class, "other.yetAnother"), //
78+
Tuple.tuple(DeleteAll.class, OtherEntity.class, "other"), //
79+
Tuple.tuple(DeleteAll.class, SomeEntity.class, null) //
80+
);
5581
}
5682

5783
@Data

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
@@ -32,6 +32,7 @@
3232
import org.springframework.data.annotation.Id;
3333
import org.springframework.data.jdbc.core.conversion.AggregateChange.Kind;
3434
import org.springframework.data.jdbc.core.conversion.DbAction.Delete;
35+
import org.springframework.data.jdbc.core.conversion.DbAction.DeleteAll;
3536
import org.springframework.data.jdbc.core.conversion.DbAction.Insert;
3637
import org.springframework.data.jdbc.core.conversion.DbAction.Update;
3738
import org.springframework.data.jdbc.core.mapping.JdbcMappingContext;
@@ -163,6 +164,39 @@ public void cascadingReferencesTriggerCascadingActions() {
163164
);
164165
}
165166

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

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
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 static org.assertj.core.api.Assertions.*;
19+
20+
import java.util.List;
21+
import java.util.Map;
22+
import java.util.Set;
23+
24+
import org.junit.Test;
25+
import org.springframework.data.jdbc.core.mapping.JdbcMappingContext;
26+
import org.springframework.data.mapping.PropertyPath;
27+
28+
/**
29+
* @author Jens Schauder
30+
*/
31+
public class JdbcMappingContextUnitTests {
32+
33+
JdbcMappingContext context = new JdbcMappingContext();
34+
35+
// DATAJDBC-188
36+
@Test
37+
public void simpleEntityDoesntReferenceOtherEntities() {
38+
39+
List<PropertyPath> paths = context.referencedEntities(SimpleEntity.class, null);
40+
41+
assertThat(paths).isEmpty();
42+
}
43+
44+
// DATAJDBC-188
45+
@Test
46+
public void cascadingReferencesGetFound() {
47+
48+
List<PropertyPath> paths = context.referencedEntities(CascadingEntity.class, null);
49+
50+
assertThat(paths).extracting(PropertyPath::toDotPath) //
51+
.containsExactly( //
52+
"reference.reference", //
53+
"reference" //
54+
);
55+
}
56+
57+
// DATAJDBC-188
58+
@Test
59+
public void setReferencesGetFound() {
60+
61+
List<PropertyPath> paths = context.referencedEntities(EntityWithSet.class, null);
62+
63+
assertThat(paths).extracting(PropertyPath::toDotPath) //
64+
.containsExactly( //
65+
"set.reference", //
66+
"set" //
67+
);
68+
}
69+
70+
// DATAJDBC-188
71+
@Test
72+
public void mapReferencesGetFound() {
73+
74+
List<PropertyPath> paths = context.referencedEntities(EntityWithMap.class, null);
75+
76+
assertThat(paths).extracting(PropertyPath::toDotPath) //
77+
.containsExactly( //
78+
"map.reference", //
79+
"map" //
80+
);
81+
}
82+
83+
private static class SimpleEntity {
84+
String name;
85+
}
86+
87+
private static class CascadingEntity {
88+
MiddleEntity reference;
89+
}
90+
91+
private static class MiddleEntity {
92+
SimpleEntity reference;
93+
}
94+
95+
private static class EntityWithMap {
96+
Map<String, MiddleEntity> map;
97+
}
98+
99+
private static class EntityWithSet {
100+
Set<MiddleEntity> set;
101+
}
102+
}

0 commit comments

Comments
 (0)