Browse Source

Polishing.

Original pull request #1228
pull/1231/head
Jens Schauder 4 years ago
parent
commit
64d9bbbd55
No known key found for this signature in database
GPG Key ID: 45CC872F17423DBF
  1. 21
      spring-data-relational/src/main/java/org/springframework/data/relational/core/conversion/SaveBatchingAggregateChange.java
  2. 42
      spring-data-relational/src/test/java/org/springframework/data/relational/core/conversion/SaveBatchingAggregateChangeTest.java

21
spring-data-relational/src/main/java/org/springframework/data/relational/core/conversion/SaveBatchingAggregateChange.java

@ -44,6 +44,10 @@ public class SaveBatchingAggregateChange<T> implements BatchingAggregateChange<T
private final Class<T> entityType; private final Class<T> entityType;
private final List<DbAction<?>> rootActions = new ArrayList<>(); private final List<DbAction<?>> rootActions = new ArrayList<>();
/**
* Holds a list of InsertRoot actions that are compatible with each other, in the sense, that they might be combined
* into a single batch.
*/
private final List<DbAction.InsertRoot<T>> insertRootBatchCandidates = new ArrayList<>(); private final List<DbAction.InsertRoot<T>> insertRootBatchCandidates = new ArrayList<>();
private final Map<PersistentPropertyPath<RelationalPersistentProperty>, Map<IdValueSource, List<DbAction.Insert<Object>>>> insertActions = // private final Map<PersistentPropertyPath<RelationalPersistentProperty>, Map<IdValueSource, List<DbAction.Insert<Object>>>> insertActions = //
new HashMap<>(); new HashMap<>();
@ -85,16 +89,21 @@ public class SaveBatchingAggregateChange<T> implements BatchingAggregateChange<T
public void add(RootAggregateChange<T> aggregateChange) { public void add(RootAggregateChange<T> aggregateChange) {
aggregateChange.forEachAction(action -> { aggregateChange.forEachAction(action -> {
if (action instanceof DbAction.UpdateRoot<?> rootAction) { if (action instanceof DbAction.UpdateRoot<?> rootAction) {
commitBatchCandidates();
combineBatchCandidatesIntoSingleBatchRootAction();
rootActions.add(rootAction); rootActions.add(rootAction);
} else if (action instanceof DbAction.InsertRoot<?> rootAction) { } else if (action instanceof DbAction.InsertRoot<?> rootAction) {
if (!insertRootBatchCandidates.isEmpty() && !insertRootBatchCandidates.get(0).getIdValueSource().equals(rootAction.getIdValueSource())) {
commitBatchCandidates(); if (!insertRootBatchCandidates.isEmpty()
&& !insertRootBatchCandidates.get(0).getIdValueSource().equals(rootAction.getIdValueSource())) {
combineBatchCandidatesIntoSingleBatchRootAction();
} }
// noinspection unchecked // noinspection unchecked
insertRootBatchCandidates.add((DbAction.InsertRoot<T>) rootAction); insertRootBatchCandidates.add((DbAction.InsertRoot<T>) rootAction);
} else if (action instanceof DbAction.Insert<?> insertAction) { } else if (action instanceof DbAction.Insert<?> insertAction) {
// noinspection unchecked // noinspection unchecked
addInsert((DbAction.Insert<Object>) insertAction); addInsert((DbAction.Insert<Object>) insertAction);
} else if (action instanceof DbAction.Delete<?> deleteAction) { } else if (action instanceof DbAction.Delete<?> deleteAction) {
@ -103,7 +112,11 @@ public class SaveBatchingAggregateChange<T> implements BatchingAggregateChange<T
}); });
} }
private void commitBatchCandidates() { /**
* All actions gathered in {@link #insertRootBatchCandidates} are combined into a single root action and the list of
* batch candidates is emptied.
*/
private void combineBatchCandidatesIntoSingleBatchRootAction() {
if (insertRootBatchCandidates.size() > 1) { if (insertRootBatchCandidates.size() > 1) {
rootActions.add(new DbAction.BatchInsertRoot<>(List.copyOf(insertRootBatchCandidates))); rootActions.add(new DbAction.BatchInsertRoot<>(List.copyOf(insertRootBatchCandidates)));

42
spring-data-relational/src/test/java/org/springframework/data/relational/core/conversion/SaveBatchingAggregateChangeTest.java

@ -70,6 +70,7 @@ class SaveBatchingAggregateChangeTest {
DbAction.InsertRoot<Root> root1Insert = new DbAction.InsertRoot<>(root1, IdValueSource.GENERATED); DbAction.InsertRoot<Root> root1Insert = new DbAction.InsertRoot<>(root1, IdValueSource.GENERATED);
RootAggregateChange<Root> aggregateChange1 = MutableAggregateChange.forSave(root1); RootAggregateChange<Root> aggregateChange1 = MutableAggregateChange.forSave(root1);
aggregateChange1.setRootAction(root1Insert); aggregateChange1.setRootAction(root1Insert);
Root root2 = new Root(1L, null); Root root2 = new Root(1L, null);
DbAction.UpdateRoot<Root> root2Update = new DbAction.UpdateRoot<>(root2, null); DbAction.UpdateRoot<Root> root2Update = new DbAction.UpdateRoot<>(root2, null);
RootAggregateChange<Root> aggregateChange2 = MutableAggregateChange.forSave(root2); RootAggregateChange<Root> aggregateChange2 = MutableAggregateChange.forSave(root2);
@ -93,11 +94,13 @@ class SaveBatchingAggregateChangeTest {
DbAction.InsertRoot<Root> root1Insert = new DbAction.InsertRoot<>(root1, IdValueSource.GENERATED); DbAction.InsertRoot<Root> root1Insert = new DbAction.InsertRoot<>(root1, IdValueSource.GENERATED);
RootAggregateChange<Root> aggregateChange1 = MutableAggregateChange.forSave(root1); RootAggregateChange<Root> aggregateChange1 = MutableAggregateChange.forSave(root1);
aggregateChange1.setRootAction(root1Insert); aggregateChange1.setRootAction(root1Insert);
Root root2 = new Root(1L, null);
Root root2 = new Root(2L, null);
DbAction.InsertRoot<Root> root2Insert = new DbAction.InsertRoot<>(root2, IdValueSource.GENERATED); DbAction.InsertRoot<Root> root2Insert = new DbAction.InsertRoot<>(root2, IdValueSource.GENERATED);
RootAggregateChange<Root> aggregateChange2 = MutableAggregateChange.forSave(root2); RootAggregateChange<Root> aggregateChange2 = MutableAggregateChange.forSave(root2);
aggregateChange2.setRootAction(root2Insert); aggregateChange2.setRootAction(root2Insert);
Root root3 = new Root(1L, null);
Root root3 = new Root(3L, null);
DbAction.UpdateRoot<Root> root3Update = new DbAction.UpdateRoot<>(root3, null); DbAction.UpdateRoot<Root> root3Update = new DbAction.UpdateRoot<>(root3, null);
RootAggregateChange<Root> aggregateChange3 = MutableAggregateChange.forSave(root3); RootAggregateChange<Root> aggregateChange3 = MutableAggregateChange.forSave(root3);
aggregateChange3.setRootAction(root3Update); aggregateChange3.setRootAction(root3Update);
@ -138,7 +141,8 @@ class SaveBatchingAggregateChangeTest {
DbAction.InsertRoot<Root> root1Insert = new DbAction.InsertRoot<>(root1, IdValueSource.GENERATED); DbAction.InsertRoot<Root> root1Insert = new DbAction.InsertRoot<>(root1, IdValueSource.GENERATED);
RootAggregateChange<Root> aggregateChange1 = MutableAggregateChange.forSave(root1); RootAggregateChange<Root> aggregateChange1 = MutableAggregateChange.forSave(root1);
aggregateChange1.setRootAction(root1Insert); aggregateChange1.setRootAction(root1Insert);
Root root2 = new Root(1L, null);
Root root2 = new Root(2L, null);
DbAction.InsertRoot<Root> root2Insert = new DbAction.InsertRoot<>(root2, IdValueSource.PROVIDED); DbAction.InsertRoot<Root> root2Insert = new DbAction.InsertRoot<>(root2, IdValueSource.PROVIDED);
RootAggregateChange<Root> aggregateChange2 = MutableAggregateChange.forSave(root2); RootAggregateChange<Root> aggregateChange2 = MutableAggregateChange.forSave(root2);
aggregateChange2.setRootAction(root2Insert); aggregateChange2.setRootAction(root2Insert);
@ -157,11 +161,13 @@ class SaveBatchingAggregateChangeTest {
DbAction.InsertRoot<Root> root1Insert = new DbAction.InsertRoot<>(root1, IdValueSource.GENERATED); DbAction.InsertRoot<Root> root1Insert = new DbAction.InsertRoot<>(root1, IdValueSource.GENERATED);
RootAggregateChange<Root> aggregateChange1 = MutableAggregateChange.forSave(root1); RootAggregateChange<Root> aggregateChange1 = MutableAggregateChange.forSave(root1);
aggregateChange1.setRootAction(root1Insert); aggregateChange1.setRootAction(root1Insert);
Root root2 = new Root(1L, null);
Root root2 = new Root(2L, null);
DbAction.InsertRoot<Root> root2Insert = new DbAction.InsertRoot<>(root2, IdValueSource.GENERATED); DbAction.InsertRoot<Root> root2Insert = new DbAction.InsertRoot<>(root2, IdValueSource.GENERATED);
RootAggregateChange<Root> aggregateChange2 = MutableAggregateChange.forSave(root2); RootAggregateChange<Root> aggregateChange2 = MutableAggregateChange.forSave(root2);
aggregateChange2.setRootAction(root2Insert); aggregateChange2.setRootAction(root2Insert);
Root root3 = new Root(1L, null);
Root root3 = new Root(3L, null);
DbAction.InsertRoot<Root> root3Insert = new DbAction.InsertRoot<>(root3, IdValueSource.PROVIDED); DbAction.InsertRoot<Root> root3Insert = new DbAction.InsertRoot<>(root3, IdValueSource.PROVIDED);
RootAggregateChange<Root> aggregateChange3 = MutableAggregateChange.forSave(root3); RootAggregateChange<Root> aggregateChange3 = MutableAggregateChange.forSave(root3);
aggregateChange3.setRootAction(root3Insert); aggregateChange3.setRootAction(root3Insert);
@ -188,7 +194,8 @@ class SaveBatchingAggregateChangeTest {
DbAction.InsertRoot<Root> root1Insert = new DbAction.InsertRoot<>(root1, IdValueSource.GENERATED); DbAction.InsertRoot<Root> root1Insert = new DbAction.InsertRoot<>(root1, IdValueSource.GENERATED);
RootAggregateChange<Root> aggregateChange1 = MutableAggregateChange.forSave(root1); RootAggregateChange<Root> aggregateChange1 = MutableAggregateChange.forSave(root1);
aggregateChange1.setRootAction(root1Insert); aggregateChange1.setRootAction(root1Insert);
Root root2 = new Root(1L, null);
Root root2 = new Root(2L, null);
DbAction.InsertRoot<Root> root2Insert = new DbAction.InsertRoot<>(root2, IdValueSource.GENERATED); DbAction.InsertRoot<Root> root2Insert = new DbAction.InsertRoot<>(root2, IdValueSource.GENERATED);
RootAggregateChange<Root> aggregateChange2 = MutableAggregateChange.forSave(root2); RootAggregateChange<Root> aggregateChange2 = MutableAggregateChange.forSave(root2);
aggregateChange2.setRootAction(root2Insert); aggregateChange2.setRootAction(root2Insert);
@ -212,10 +219,12 @@ class SaveBatchingAggregateChangeTest {
DbAction.InsertRoot<Root> root1Insert = new DbAction.InsertRoot<>(root1, IdValueSource.GENERATED); DbAction.InsertRoot<Root> root1Insert = new DbAction.InsertRoot<>(root1, IdValueSource.GENERATED);
RootAggregateChange<Root> aggregateChange1 = MutableAggregateChange.forSave(root1); RootAggregateChange<Root> aggregateChange1 = MutableAggregateChange.forSave(root1);
aggregateChange1.setRootAction(root1Insert); aggregateChange1.setRootAction(root1Insert);
Root root2 = new Root(2L, null); Root root2 = new Root(2L, null);
DbAction.InsertRoot<Root> root2Insert = new DbAction.InsertRoot<>(root2, IdValueSource.GENERATED); DbAction.InsertRoot<Root> root2Insert = new DbAction.InsertRoot<>(root2, IdValueSource.GENERATED);
RootAggregateChange<Root> aggregateChange2 = MutableAggregateChange.forSave(root2); RootAggregateChange<Root> aggregateChange2 = MutableAggregateChange.forSave(root2);
aggregateChange2.setRootAction(root2Insert); aggregateChange2.setRootAction(root2Insert);
BatchingAggregateChange<Root, RootAggregateChange<Root>> change = BatchingAggregateChange.forSave(Root.class); BatchingAggregateChange<Root, RootAggregateChange<Root>> change = BatchingAggregateChange.forSave(Root.class);
change.add(aggregateChange1); change.add(aggregateChange1);
@ -242,9 +251,11 @@ class SaveBatchingAggregateChangeTest {
DbAction.UpdateRoot<Root> root1Update = new DbAction.UpdateRoot<>(root1, null); DbAction.UpdateRoot<Root> root1Update = new DbAction.UpdateRoot<>(root1, null);
RootAggregateChange<Root> aggregateChange1 = MutableAggregateChange.forSave(root1); RootAggregateChange<Root> aggregateChange1 = MutableAggregateChange.forSave(root1);
aggregateChange1.setRootAction(root1Update); aggregateChange1.setRootAction(root1Update);
DbAction.Delete<?> root1IntermediateDelete = new DbAction.Delete<>(1L, DbAction.Delete<?> root1IntermediateDelete = new DbAction.Delete<>(1L,
context.getPersistentPropertyPath("intermediate", Root.class)); context.getPersistentPropertyPath("intermediate", Root.class));
aggregateChange1.addAction(root1IntermediateDelete); aggregateChange1.addAction(root1IntermediateDelete);
Root root2 = new Root(null, null); Root root2 = new Root(null, null);
DbAction.InsertRoot<Root> root2Insert = new DbAction.InsertRoot<>(root2, IdValueSource.GENERATED); DbAction.InsertRoot<Root> root2Insert = new DbAction.InsertRoot<>(root2, IdValueSource.GENERATED);
RootAggregateChange<Root> aggregateChange2 = MutableAggregateChange.forSave(root2); RootAggregateChange<Root> aggregateChange2 = MutableAggregateChange.forSave(root2);
@ -270,12 +281,14 @@ class SaveBatchingAggregateChangeTest {
context.getPersistentPropertyPath("intermediate", Root.class)); context.getPersistentPropertyPath("intermediate", Root.class));
aggregateChange1.addAction(root1IntermediateDelete); aggregateChange1.addAction(root1IntermediateDelete);
Root root2 = new Root(1L, null); Root root2 = new Root(2L, null);
RootAggregateChange<Root> aggregateChange2 = MutableAggregateChange.forSave(root2); RootAggregateChange<Root> aggregateChange2 = MutableAggregateChange.forSave(root2);
aggregateChange2.setRootAction(new DbAction.UpdateRoot<>(root2, null)); aggregateChange2.setRootAction(new DbAction.UpdateRoot<>(root2, null));
DbAction.Delete<?> root2LeafDelete = new DbAction.Delete<>(1L, DbAction.Delete<?> root2LeafDelete = new DbAction.Delete<>(1L,
context.getPersistentPropertyPath("intermediate.leaf", Root.class)); context.getPersistentPropertyPath("intermediate.leaf", Root.class));
aggregateChange2.addAction(root2LeafDelete); aggregateChange2.addAction(root2LeafDelete);
DbAction.Delete<?> root2IntermediateDelete = new DbAction.Delete<>(1L, DbAction.Delete<?> root2IntermediateDelete = new DbAction.Delete<>(1L,
context.getPersistentPropertyPath("intermediate", Root.class)); context.getPersistentPropertyPath("intermediate", Root.class));
aggregateChange2.addAction(root2IntermediateDelete); aggregateChange2.addAction(root2IntermediateDelete);
@ -325,10 +338,12 @@ class SaveBatchingAggregateChangeTest {
DbAction.InsertRoot<Root> rootInsert = new DbAction.InsertRoot<>(root, IdValueSource.GENERATED); DbAction.InsertRoot<Root> rootInsert = new DbAction.InsertRoot<>(root, IdValueSource.GENERATED);
RootAggregateChange<Root> aggregateChange = MutableAggregateChange.forSave(root); RootAggregateChange<Root> aggregateChange = MutableAggregateChange.forSave(root);
aggregateChange.setRootAction(rootInsert); aggregateChange.setRootAction(rootInsert);
Intermediate intermediateGeneratedId = new Intermediate(null, "intermediateGeneratedId", null); Intermediate intermediateGeneratedId = new Intermediate(null, "intermediateGeneratedId", null);
DbAction.Insert<Intermediate> intermediateInsertGeneratedId = new DbAction.Insert<>(intermediateGeneratedId, DbAction.Insert<Intermediate> intermediateInsertGeneratedId = new DbAction.Insert<>(intermediateGeneratedId,
context.getPersistentPropertyPath("intermediate", Root.class), rootInsert, emptyMap(), IdValueSource.GENERATED); context.getPersistentPropertyPath("intermediate", Root.class), rootInsert, emptyMap(), IdValueSource.GENERATED);
aggregateChange.addAction(intermediateInsertGeneratedId); aggregateChange.addAction(intermediateInsertGeneratedId);
Intermediate intermediateProvidedId = new Intermediate(123L, "intermediateProvidedId", null); Intermediate intermediateProvidedId = new Intermediate(123L, "intermediateProvidedId", null);
DbAction.Insert<Intermediate> intermediateInsertProvidedId = new DbAction.Insert<>(intermediateProvidedId, DbAction.Insert<Intermediate> intermediateInsertProvidedId = new DbAction.Insert<>(intermediateProvidedId,
context.getPersistentPropertyPath("intermediate", Root.class), rootInsert, emptyMap(), IdValueSource.PROVIDED); context.getPersistentPropertyPath("intermediate", Root.class), rootInsert, emptyMap(), IdValueSource.PROVIDED);
@ -360,11 +375,13 @@ class SaveBatchingAggregateChangeTest {
DbAction.InsertRoot<Root> root1Insert = new DbAction.InsertRoot<>(root1, IdValueSource.GENERATED); DbAction.InsertRoot<Root> root1Insert = new DbAction.InsertRoot<>(root1, IdValueSource.GENERATED);
RootAggregateChange<Root> aggregateChange1 = MutableAggregateChange.forSave(root1); RootAggregateChange<Root> aggregateChange1 = MutableAggregateChange.forSave(root1);
aggregateChange1.setRootAction(root1Insert); aggregateChange1.setRootAction(root1Insert);
Intermediate root1Intermediate = new Intermediate(null, "root1Intermediate", null); Intermediate root1Intermediate = new Intermediate(null, "root1Intermediate", null);
DbAction.Insert<Intermediate> root1IntermediateInsert = new DbAction.Insert<>(root1Intermediate, DbAction.Insert<Intermediate> root1IntermediateInsert = new DbAction.Insert<>(root1Intermediate,
context.getPersistentPropertyPath("intermediate", Root.class), root1Insert, emptyMap(), context.getPersistentPropertyPath("intermediate", Root.class), root1Insert, emptyMap(),
IdValueSource.GENERATED); IdValueSource.GENERATED);
aggregateChange1.addAction(root1IntermediateInsert); aggregateChange1.addAction(root1IntermediateInsert);
Leaf root1Leaf = new Leaf(null, "root1Leaf"); Leaf root1Leaf = new Leaf(null, "root1Leaf");
DbAction.Insert<Leaf> root1LeafInsert = new DbAction.Insert<>(root1Leaf, DbAction.Insert<Leaf> root1LeafInsert = new DbAction.Insert<>(root1Leaf,
context.getPersistentPropertyPath("intermediate.leaf", Root.class), root1IntermediateInsert, emptyMap(), context.getPersistentPropertyPath("intermediate.leaf", Root.class), root1IntermediateInsert, emptyMap(),
@ -375,6 +392,7 @@ class SaveBatchingAggregateChangeTest {
DbAction.InsertRoot<Root> root2Insert = new DbAction.InsertRoot<>(root2, IdValueSource.GENERATED); DbAction.InsertRoot<Root> root2Insert = new DbAction.InsertRoot<>(root2, IdValueSource.GENERATED);
RootAggregateChange<Root> aggregateChange2 = MutableAggregateChange.forSave(root2); RootAggregateChange<Root> aggregateChange2 = MutableAggregateChange.forSave(root2);
aggregateChange2.setRootAction(root2Insert); aggregateChange2.setRootAction(root2Insert);
Intermediate root2Intermediate = new Intermediate(null, "root2Intermediate", null); Intermediate root2Intermediate = new Intermediate(null, "root2Intermediate", null);
DbAction.Insert<Intermediate> root2IntermediateInsert = new DbAction.Insert<>(root2Intermediate, DbAction.Insert<Intermediate> root2IntermediateInsert = new DbAction.Insert<>(root2Intermediate,
context.getPersistentPropertyPath("intermediate", Root.class), root2Insert, emptyMap(), context.getPersistentPropertyPath("intermediate", Root.class), root2Insert, emptyMap(),
@ -405,11 +423,13 @@ class SaveBatchingAggregateChangeTest {
IdValueSource.GENERATED); IdValueSource.GENERATED);
RootAggregateChange<RootWithSameLengthReferences> aggregateChange = MutableAggregateChange.forSave(root); RootAggregateChange<RootWithSameLengthReferences> aggregateChange = MutableAggregateChange.forSave(root);
aggregateChange.setRootAction(rootInsert); aggregateChange.setRootAction(rootInsert);
Intermediate one = new Intermediate(null, "one", null); Intermediate one = new Intermediate(null, "one", null);
DbAction.Insert<Intermediate> oneInsert = new DbAction.Insert<>(one, DbAction.Insert<Intermediate> oneInsert = new DbAction.Insert<>(one,
context.getPersistentPropertyPath("one", RootWithSameLengthReferences.class), rootInsert, emptyMap(), context.getPersistentPropertyPath("one", RootWithSameLengthReferences.class), rootInsert, emptyMap(),
IdValueSource.GENERATED); IdValueSource.GENERATED);
aggregateChange.addAction(oneInsert); aggregateChange.addAction(oneInsert);
Intermediate two = new Intermediate(null, "two", null); Intermediate two = new Intermediate(null, "two", null);
DbAction.Insert<Intermediate> twoInsert = new DbAction.Insert<>(two, DbAction.Insert<Intermediate> twoInsert = new DbAction.Insert<>(two,
context.getPersistentPropertyPath("two", RootWithSameLengthReferences.class), rootInsert, emptyMap(), context.getPersistentPropertyPath("two", RootWithSameLengthReferences.class), rootInsert, emptyMap(),
@ -426,8 +446,8 @@ class SaveBatchingAggregateChangeTest {
.containsSubsequence( // .containsSubsequence( //
Tuple.tuple(DbAction.BatchInsert.class, Intermediate.class, IdValueSource.GENERATED), Tuple.tuple(DbAction.BatchInsert.class, Intermediate.class, IdValueSource.GENERATED),
Tuple.tuple(DbAction.BatchInsert.class, Intermediate.class, IdValueSource.GENERATED)); Tuple.tuple(DbAction.BatchInsert.class, Intermediate.class, IdValueSource.GENERATED));
List<DbAction.BatchWithValue<Intermediate, DbAction<Intermediate>, Object>> batchInsertActions = getBatchWithValueActions(actions, Intermediate.class, List<DbAction.BatchWithValue<Intermediate, DbAction<Intermediate>, Object>> batchInsertActions = getBatchWithValueActions(
DbAction.BatchInsert.class); actions, Intermediate.class, DbAction.BatchInsert.class);
assertThat(batchInsertActions).hasSize(2); assertThat(batchInsertActions).hasSize(2);
assertThat(batchInsertActions.get(0).getActions()).containsExactly(oneInsert); assertThat(batchInsertActions.get(0).getActions()).containsExactly(oneInsert);
assertThat(batchInsertActions.get(1).getActions()).containsExactly(twoInsert); assertThat(batchInsertActions.get(1).getActions()).containsExactly(twoInsert);
@ -467,6 +487,7 @@ class SaveBatchingAggregateChangeTest {
@Value @Value
static class RootWithSameLengthReferences { static class RootWithSameLengthReferences {
@Id Long id; @Id Long id;
Intermediate one; Intermediate one;
Intermediate two; Intermediate two;
@ -474,12 +495,14 @@ class SaveBatchingAggregateChangeTest {
@Value @Value
static class Root { static class Root {
@Id Long id; @Id Long id;
Intermediate intermediate; Intermediate intermediate;
} }
@Value @Value
static class Intermediate { static class Intermediate {
@Id Long id; @Id Long id;
String name; String name;
Leaf leaf; Leaf leaf;
@ -487,6 +510,7 @@ class SaveBatchingAggregateChangeTest {
@Value @Value
static class Leaf { static class Leaf {
@Id Long id; @Id Long id;
String name; String name;
} }

Loading…
Cancel
Save