Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 21b74e2

Browse files
mipo256schauder
authored andcommitted
Applies proper event handling before saving in batch.
Signed-off-by: mipo256 <mikhailpolivakha@gmail.com> Commit message edited by Jens Schauder. Original pull request #2065 Closes #2064
1 parent 243c060 commit 21b74e2

10 files changed

+168
-21
lines changed

‎spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/JdbcAggregateTemplate.java‎

Lines changed: 48 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import java.util.stream.Stream;
2929
import java.util.stream.StreamSupport;
3030

31+
import org.jspecify.annotations.Nullable;
3132
import org.springframework.context.ApplicationContext;
3233
import org.springframework.context.ApplicationEventPublisher;
3334
import org.springframework.data.domain.Page;
@@ -50,11 +51,22 @@
5051
import org.springframework.data.relational.core.mapping.RelationalMappingContext;
5152
import org.springframework.data.relational.core.mapping.RelationalPersistentEntity;
5253
import org.springframework.data.relational.core.mapping.RelationalPersistentProperty;
53-
import org.springframework.data.relational.core.mapping.event.*;
54+
import org.springframework.data.relational.core.mapping.event.AbstractRelationalEvent;
55+
import org.springframework.data.relational.core.mapping.event.AfterConvertCallback;
56+
import org.springframework.data.relational.core.mapping.event.AfterConvertEvent;
57+
import org.springframework.data.relational.core.mapping.event.AfterDeleteCallback;
58+
import org.springframework.data.relational.core.mapping.event.AfterDeleteEvent;
59+
import org.springframework.data.relational.core.mapping.event.AfterSaveCallback;
60+
import org.springframework.data.relational.core.mapping.event.AfterSaveEvent;
61+
import org.springframework.data.relational.core.mapping.event.BeforeConvertCallback;
62+
import org.springframework.data.relational.core.mapping.event.BeforeConvertEvent;
63+
import org.springframework.data.relational.core.mapping.event.BeforeDeleteCallback;
64+
import org.springframework.data.relational.core.mapping.event.BeforeDeleteEvent;
65+
import org.springframework.data.relational.core.mapping.event.BeforeSaveCallback;
66+
import org.springframework.data.relational.core.mapping.event.BeforeSaveEvent;
67+
import org.springframework.data.relational.core.mapping.event.Identifier;
5468
import org.springframework.data.relational.core.query.Query;
5569
import org.springframework.data.support.PageableExecutionUtils;
56-
import org.springframework.data.util.Streamable;
57-
import org.springframework.lang.Nullable;
5870
import org.springframework.util.Assert;
5971
import org.springframework.util.ClassUtils;
6072

@@ -175,7 +187,7 @@ public <T> T save(T instance) {
175187

176188
@Override
177189
public <T> List<T> saveAll(Iterable<T> instances) {
178-
return doInBatch(instances, (first) -> (second -> changeCreatorSelectorForSave(first).apply(second)));
190+
return saveInBatch(instances, instance -> changeCreatorSelectorForSave(instance));
179191
}
180192

181193
/**
@@ -196,7 +208,7 @@ public <T> T insert(T instance) {
196208

197209
@Override
198210
public <T> List<T> insertAll(Iterable<T> instances) {
199-
return doInBatch(instances, (__) -> (entity -> createInsertChange(prepareVersionForInsert(entity))));
211+
return doInBatch(instances, entity -> createInsertChange(prepareVersionForInsert(entity)));
200212
}
201213

202214
/**
@@ -217,10 +229,28 @@ public <T> T update(T instance) {
217229

218230
@Override
219231
public <T> List<T> updateAll(Iterable<T> instances) {
220-
return doInBatch(instances, (__) -> (entity -> createUpdateChange(prepareVersionForUpdate(entity))));
232+
return doInBatch(instances, entity -> createUpdateChange(prepareVersionForUpdate(entity)));
221233
}
222234

223-
private <T> List<T> doInBatch(Iterable<T> instances,Function<T, Function<T, RootAggregateChange<T>>> changeCreatorFunction) {
235+
private <T> List<T> saveInBatch(Iterable<T> instances, Function<T, AggregateChangeCreator<T>> changes) {
236+
237+
Assert.notNull(instances, "Aggregate instances must not be null");
238+
239+
if (!instances.iterator().hasNext()) {
240+
return Collections.emptyList();
241+
}
242+
243+
List<EntityAndChangeCreator<T>> entityAndChangeCreators = new ArrayList<>();
244+
245+
for (T instance : instances) {
246+
verifyIdProperty(instance);
247+
entityAndChangeCreators.add(new EntityAndChangeCreator<>(instance, changes.apply(instance)));
248+
}
249+
250+
return performSaveAll(entityAndChangeCreators);
251+
}
252+
253+
private <T> List<T> doInBatch(Iterable<T> instances, AggregateChangeCreator<T> changeCreatorFunction) {
224254

225255
Assert.notNull(instances, "Aggregate instances must not be null");
226256

@@ -231,7 +261,7 @@ private <T> List<T> doInBatch(Iterable<T> instances,Function<T, Function<T, Root
231261
List<EntityAndChangeCreator<T>> entityAndChangeCreators = new ArrayList<>();
232262
for (T instance : instances) {
233263
verifyIdProperty(instance);
234-
entityAndChangeCreators.add(new EntityAndChangeCreator<T>(instance, changeCreatorFunction.apply(instance)));
264+
entityAndChangeCreators.add(new EntityAndChangeCreator<T>(instance, changeCreatorFunction));
235265
}
236266
return performSaveAll(entityAndChangeCreators);
237267
}
@@ -484,7 +514,7 @@ private <T> RootAggregateChange<T> beforeExecute(EntityAndChangeCreator<T> insta
484514

485515
T aggregateRoot = triggerBeforeConvert(instance.entity);
486516

487-
RootAggregateChange<T> change = instance.changeCreator.apply(aggregateRoot);
517+
RootAggregateChange<T> change = instance.changeCreator.createAggregateChange(aggregateRoot);
488518

489519
aggregateRoot = triggerBeforeSave(change.getRoot(), change);
490520

@@ -542,7 +572,7 @@ private <T> List<T> performSaveAll(Iterable<EntityAndChangeCreator<T>> instances
542572
return results;
543573
}
544574

545-
private <T> Function<T, RootAggregateChange<T>> changeCreatorSelectorForSave(T instance) {
575+
private <T> AggregateChangeCreator<T> changeCreatorSelectorForSave(T instance) {
546576

547577
return context.getRequiredPersistentEntity(instance.getClass()).isNew(instance)
548578
? entity -> createInsertChange(prepareVersionForInsert(entity))
@@ -681,6 +711,13 @@ private <T> T triggerBeforeDelete(@Nullable T aggregateRoot, Object id, MutableA
681711
private record EntityAndPreviousVersion<T> (T entity, @Nullable Number version) {
682712
}
683713

684-
private record EntityAndChangeCreator<T> (T entity, Function<T, RootAggregateChange<T>> changeCreator) {
714+
private record EntityAndChangeCreator<T> (T entity, AggregateChangeCreator<T> changeCreator) {
715+
}
716+
717+
private interface AggregateChangeCreator<T> extends Function<T, RootAggregateChange<T>> {
718+
719+
default RootAggregateChange<T> createAggregateChange(T instance) {
720+
return this.apply(instance);
721+
}
685722
}
686723
}

‎spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/AbstractJdbcAggregateTemplateIntegrationTests.java‎

Lines changed: 56 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,10 @@
2929
import java.util.stream.IntStream;
3030
import java.util.stream.Stream;
3131

32+
import org.assertj.core.api.Assertions;
3233
import org.junit.jupiter.api.Test;
3334
import org.springframework.beans.factory.annotation.Autowired;
35+
import org.springframework.context.ApplicationContext;
3436
import org.springframework.context.ApplicationEventPublisher;
3537
import org.springframework.context.annotation.Bean;
3638
import org.springframework.context.annotation.Configuration;
@@ -52,13 +54,15 @@
5254
import org.springframework.data.jdbc.testing.TestClass;
5355
import org.springframework.data.jdbc.testing.TestConfiguration;
5456
import org.springframework.data.jdbc.testing.TestDatabaseFeatures;
57+
import org.springframework.data.mapping.callback.EntityCallbacks;
5558
import org.springframework.data.mapping.context.InvalidPersistentPropertyPath;
5659
import org.springframework.data.relational.core.mapping.Column;
5760
import org.springframework.data.relational.core.mapping.Embedded;
5861
import org.springframework.data.relational.core.mapping.InsertOnlyProperty;
5962
import org.springframework.data.relational.core.mapping.MappedCollection;
6063
import org.springframework.data.relational.core.mapping.RelationalMappingContext;
6164
import org.springframework.data.relational.core.mapping.Table;
65+
import org.springframework.data.relational.core.mapping.event.BeforeConvertCallback;
6266
import org.springframework.data.relational.core.query.Criteria;
6367
import org.springframework.data.relational.core.query.CriteriaDefinition;
6468
import org.springframework.data.relational.core.query.Query;
@@ -1371,6 +1375,22 @@ void mapWithEnumKey() {
13711375
assertThat(enumMapOwners).containsExactly(enumMapOwner);
13721376
}
13731377

1378+
@Test //GH-2064
1379+
void saveAllBeforeConvertCallback() {
1380+
var first = new BeforeConvertCallbackForSaveBatch("first");
1381+
var second = new BeforeConvertCallbackForSaveBatch("second");
1382+
var third = new BeforeConvertCallbackForSaveBatch("third");
1383+
1384+
template.saveAll(List.of(first, second, third));
1385+
1386+
var allEntriesInTable = template.findAll(BeforeConvertCallbackForSaveBatch.class);
1387+
1388+
Assertions.assertThat(allEntriesInTable)
1389+
.hasSize(3)
1390+
.extracting(BeforeConvertCallbackForSaveBatch::getName)
1391+
.containsOnly("first", "second", "third");
1392+
}
1393+
13741394
@Test // GH-1684
13751395
void oneToOneWithIdenticalIdColumnName() {
13761396

@@ -2182,6 +2202,32 @@ public Short getVersion() {
21822202
}
21832203
}
21842204

2205+
@Table("BEFORE_CONVERT_CALLBACK_FOR_SAVE_BATCH")
2206+
static class BeforeConvertCallbackForSaveBatch {
2207+
2208+
@Id
2209+
private String id;
2210+
2211+
private String name;
2212+
2213+
public BeforeConvertCallbackForSaveBatch(String name) {
2214+
this.name = name;
2215+
}
2216+
2217+
public String getId() {
2218+
return id;
2219+
}
2220+
2221+
public BeforeConvertCallbackForSaveBatch setId(String id) {
2222+
this.id = id;
2223+
return this;
2224+
}
2225+
2226+
public String getName() {
2227+
return name;
2228+
}
2229+
}
2230+
21852231
@Table("VERSIONED_AGGREGATE")
21862232
static class AggregateWithPrimitiveShortVersion extends VersionedAggregate {
21872233

@@ -2269,9 +2315,17 @@ TestClass testClass() {
22692315
}
22702316

22712317
@Bean
2272-
JdbcAggregateOperations operations(ApplicationEventPublisher publisher, RelationalMappingContext context,
2318+
BeforeConvertCallback<BeforeConvertCallbackForSaveBatch> callback() {
2319+
return aggregate -> {
2320+
aggregate.setId(UUID.randomUUID().toString());
2321+
return aggregate;
2322+
};
2323+
}
2324+
2325+
@Bean
2326+
JdbcAggregateOperations operations(ApplicationContext applicationContext, RelationalMappingContext context,
22732327
DataAccessStrategy dataAccessStrategy, JdbcConverter converter) {
2274-
return new JdbcAggregateTemplate(publisher, context, converter, dataAccessStrategy);
2328+
return new JdbcAggregateTemplate(applicationContext, context, converter, dataAccessStrategy);
22752329
}
22762330
}
22772331

‎spring-data-jdbc/src/test/resources/org.springframework.data.jdbc.core/JdbcAggregateTemplateIntegrationTests-db2.sql‎

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,8 @@ DROP TABLE THIRD;
5959
DROP TABLE SEC;
6060
DROP TABLE FIRST;
6161

62+
DROP TABLE BEFORE_CONVERT_CALLBACK_FOR_SAVE_BATCH;
63+
6264
CREATE TABLE LEGO_SET
6365
(
6466
"id1" BIGINT GENERATED BY DEFAULT AS IDENTITY (START WITH 1) PRIMARY KEY,
@@ -467,4 +469,10 @@ CREATE TABLE THIRD
467469
SEC BIGINT NOT NULL,
468470
NAME VARCHAR(20) NOT NULL,
469471
FOREIGN KEY (SEC) REFERENCES SEC (ID)
470-
);
472+
);
473+
474+
CREATE TABLE BEFORE_CONVERT_CALLBACK_FOR_SAVE_BATCH
475+
(
476+
ID VARCHAR(36) PRIMARY KEY NOT NULL,
477+
NAME VARCHAR(20)
478+
);

‎spring-data-jdbc/src/test/resources/org.springframework.data.jdbc.core/JdbcAggregateTemplateIntegrationTests-h2.sql‎

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -417,4 +417,10 @@ CREATE TABLE THIRD
417417
SEC BIGINT NOT NULL,
418418
NAME VARCHAR(20) NOT NULL,
419419
FOREIGN KEY (SEC) REFERENCES SEC (ID)
420-
);
420+
);
421+
422+
CREATE TABLE BEFORE_CONVERT_CALLBACK_FOR_SAVE_BATCH
423+
(
424+
ID VARCHAR PRIMARY KEY,
425+
NAME VARCHAR
426+
);

‎spring-data-jdbc/src/test/resources/org.springframework.data.jdbc.core/JdbcAggregateTemplateIntegrationTests-hsql.sql‎

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -419,4 +419,10 @@ CREATE TABLE THIRD
419419
SEC BIGINT NOT NULL,
420420
NAME VARCHAR(20) NOT NULL,
421421
FOREIGN KEY (SEC) REFERENCES SEC (ID)
422-
);
422+
);
423+
424+
CREATE TABLE BEFORE_CONVERT_CALLBACK_FOR_SAVE_BATCH
425+
(
426+
ID VARCHAR PRIMARY KEY,
427+
NAME VARCHAR
428+
);

‎spring-data-jdbc/src/test/resources/org.springframework.data.jdbc.core/JdbcAggregateTemplateIntegrationTests-mariadb.sql‎

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -391,4 +391,10 @@ CREATE TABLE THIRD
391391
SEC BIGINT NOT NULL,
392392
NAME VARCHAR(20) NOT NULL,
393393
FOREIGN KEY (SEC) REFERENCES SEC (ID)
394-
);
394+
);
395+
396+
CREATE TABLE BEFORE_CONVERT_CALLBACK_FOR_SAVE_BATCH
397+
(
398+
ID VARCHAR(36) PRIMARY KEY,
399+
NAME VARCHAR(20)
400+
);

‎spring-data-jdbc/src/test/resources/org.springframework.data.jdbc.core/JdbcAggregateTemplateIntegrationTests-mssql.sql‎

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -441,4 +441,12 @@ CREATE TABLE THIRD
441441
SEC BIGINT NOT NULL,
442442
NAME VARCHAR(20) NOT NULL,
443443
FOREIGN KEY (SEC) REFERENCES SEC (ID)
444-
);
444+
);
445+
446+
DROP TABLE BEFORE_CONVERT_CALLBACK_FOR_SAVE_BATCH;
447+
448+
CREATE TABLE BEFORE_CONVERT_CALLBACK_FOR_SAVE_BATCH
449+
(
450+
ID VARCHAR PRIMARY KEY,
451+
NAME VARCHAR
452+
);

‎spring-data-jdbc/src/test/resources/org.springframework.data.jdbc.core/JdbcAggregateTemplateIntegrationTests-mysql.sql‎

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -397,4 +397,10 @@ CREATE TABLE THIRD
397397
SEC BIGINT NOT NULL,
398398
NAME VARCHAR(20) NOT NULL,
399399
FOREIGN KEY (SEC) REFERENCES SEC (ID)
400-
);
400+
);
401+
402+
CREATE TABLE BEFORE_CONVERT_CALLBACK_FOR_SAVE_BATCH
403+
(
404+
ID VARCHAR(36) PRIMARY KEY,
405+
NAME VARCHAR(20)
406+
);

‎spring-data-jdbc/src/test/resources/org.springframework.data.jdbc.core/JdbcAggregateTemplateIntegrationTests-oracle.sql‎

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ DROP TABLE THIRD CASCADE CONSTRAINTS PURGE;
4949
DROP TABLE SEC CASCADE CONSTRAINTS PURGE;
5050
DROP TABLE FIRST CASCADE CONSTRAINTS PURGE;
5151

52+
DROP TABLE BEFORE_CONVERT_CALLBACK_FOR_SAVE_BATCH CASCADE CONSTRAINTS PURGE;
53+
5254
CREATE TABLE LEGO_SET
5355
(
5456
"id1" NUMBER GENERATED by default on null as IDENTITY PRIMARY KEY,
@@ -447,4 +449,10 @@ CREATE TABLE THIRD
447449
SEC NUMBER NOT NULL,
448450
NAME VARCHAR(20) NOT NULL,
449451
FOREIGN KEY (SEC) REFERENCES SEC (ID)
450-
);
452+
);
453+
454+
CREATE TABLE BEFORE_CONVERT_CALLBACK_FOR_SAVE_BATCH
455+
(
456+
ID VARCHAR PRIMARY KEY,
457+
NAME VARCHAR
458+
);

‎spring-data-jdbc/src/test/resources/org.springframework.data.jdbc.core/JdbcAggregateTemplateIntegrationTests-postgres.sql‎

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ DROP TABLE THIRD;
5252
DROP TABLE SEC;
5353
DROP TABLE FIRST;
5454

55+
DROP TABLE "BEFORE_CONVERT_CALLBACK_FOR_SAVE_BATCH";
56+
5557
CREATE TABLE LEGO_SET
5658
(
5759
"id1" SERIAL PRIMARY KEY,
@@ -470,4 +472,10 @@ CREATE TABLE THIRD
470472
SEC BIGINT NOT NULL,
471473
NAME VARCHAR(20) NOT NULL,
472474
FOREIGN KEY (SEC) REFERENCES SEC (ID)
473-
);
475+
);
476+
477+
CREATE TABLE "BEFORE_CONVERT_CALLBACK_FOR_SAVE_BATCH"
478+
(
479+
ID VARCHAR PRIMARY KEY,
480+
NAME VARCHAR
481+
);

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /