11/*
2- * Copyright 2017-2021 the original author or authors.
2+ * Copyright 2017-2022 the original author or authors.
33 *
44 * Licensed under the Apache License, Version 2.0 (the "License");
55 * you may not use this file except in compliance with the License.
3535import org .springframework .data .relational .core .conversion .RelationalEntityDeleteWriter ;
3636import org .springframework .data .relational .core .conversion .RelationalEntityInsertWriter ;
3737import org .springframework .data .relational .core .conversion .RelationalEntityUpdateWriter ;
38+ import org .springframework .data .relational .core .conversion .RelationalEntityVersionUtils ;
3839import org .springframework .data .relational .core .mapping .RelationalMappingContext ;
3940import org .springframework .data .relational .core .mapping .RelationalPersistentEntity ;
41+ import org .springframework .data .relational .core .mapping .RelationalPersistentProperty ;
4042import org .springframework .data .relational .core .mapping .event .*;
4143import org .springframework .data .support .PageableExecutionUtils ;
4244import org .springframework .lang .Nullable ;
5153 * @author Christoph Strobl
5254 * @author Milan Milanov
5355 * @author Myeonghyeon Lee
56+ * @author Chirag Tailor
5457 */
5558public class JdbcAggregateTemplate implements JdbcAggregateOperations {
5659
@@ -63,6 +66,7 @@ public class JdbcAggregateTemplate implements JdbcAggregateOperations {
6366
6467private final DataAccessStrategy accessStrategy ;
6568private final AggregateChangeExecutor executor ;
69+ private final JdbcConverter converter ;
6670
6771private EntityCallbacks entityCallbacks = EntityCallbacks .create ();
6872
@@ -86,6 +90,7 @@ public JdbcAggregateTemplate(ApplicationContext publisher, RelationalMappingCont
8690this .publisher = publisher ;
8791this .context = context ;
8892this .accessStrategy = dataAccessStrategy ;
93+ this .converter = converter ;
8994
9095this .jdbcEntityInsertWriter = new RelationalEntityInsertWriter (context );
9196this .jdbcEntityUpdateWriter = new RelationalEntityUpdateWriter (context );
@@ -115,6 +120,7 @@ public JdbcAggregateTemplate(ApplicationEventPublisher publisher, RelationalMapp
115120this .publisher = publisher ;
116121this .context = context ;
117122this .accessStrategy = dataAccessStrategy ;
123+ this .converter = converter ;
118124
119125this .jdbcEntityInsertWriter = new RelationalEntityInsertWriter (context );
120126this .jdbcEntityUpdateWriter = new RelationalEntityUpdateWriter (context );
@@ -288,7 +294,7 @@ private <T> T store(T aggregateRoot, Function<T, MutableAggregateChange<T>> chan
288294
289295MutableAggregateChange <T > change = changeCreator .apply (aggregateRoot );
290296
291- aggregateRoot = triggerBeforeSave (aggregateRoot , change );
297+ aggregateRoot = triggerBeforeSave (change . getEntity () , change );
292298
293299change .setEntity (aggregateRoot );
294300
@@ -315,21 +321,58 @@ private <T> void deleteTree(Object id, @Nullable T entity, Class<T> domainType)
315321
316322private <T > MutableAggregateChange <T > createInsertChange (T instance ) {
317323
318- MutableAggregateChange <T > aggregateChange = MutableAggregateChange .forSave (instance );
319- jdbcEntityInsertWriter .write (instance , aggregateChange );
324+ RelationalPersistentEntity <T > persistentEntity = getRequiredPersistentEntity (instance );
325+ T preparedInstance = instance ;
326+ if (persistentEntity .hasVersionProperty ()) {
327+ RelationalPersistentProperty versionProperty = persistentEntity .getRequiredVersionProperty ();
328+
329+ long initialVersion = versionProperty .getActualType ().isPrimitive () ? 1L : 0 ;
330+
331+ preparedInstance = RelationalEntityVersionUtils .setVersionNumberOnEntity ( //
332+ instance , initialVersion , persistentEntity , converter );
333+ }
334+ MutableAggregateChange <T > aggregateChange = MutableAggregateChange .forSave (preparedInstance );
335+ jdbcEntityInsertWriter .write (preparedInstance , aggregateChange );
320336return aggregateChange ;
321337}
322338
323339private <T > MutableAggregateChange <T > createUpdateChange (T instance ) {
324340
325- MutableAggregateChange <T > aggregateChange = MutableAggregateChange .forSave (instance );
326- jdbcEntityUpdateWriter .write (instance , aggregateChange );
341+ RelationalPersistentEntity <T > persistentEntity = getRequiredPersistentEntity (instance );
342+ T preparedInstance = instance ;
343+ Number previousVersion = null ;
344+ if (persistentEntity .hasVersionProperty ()) {
345+ // If the root aggregate has a version property, increment it.
346+ previousVersion = RelationalEntityVersionUtils .getVersionNumberFromEntity (instance ,
347+ persistentEntity , converter );
348+
349+ Assert .notNull (previousVersion , "The root aggregate cannot be updated because the version property is null." );
350+
351+ long newVersion = previousVersion .longValue () + 1 ;
352+
353+ preparedInstance = RelationalEntityVersionUtils .setVersionNumberOnEntity (instance , newVersion ,
354+ persistentEntity , converter );
355+ }
356+ MutableAggregateChange <T > aggregateChange = MutableAggregateChange .forSave (preparedInstance , previousVersion );
357+ jdbcEntityUpdateWriter .write (preparedInstance , aggregateChange );
327358return aggregateChange ;
328359}
329360
361+ @ SuppressWarnings ("unchecked" )
362+ private <T > RelationalPersistentEntity <T > getRequiredPersistentEntity (T instance ) {
363+ return (RelationalPersistentEntity <T >) context .getRequiredPersistentEntity (instance .getClass ());
364+ }
365+
330366private <T > MutableAggregateChange <T > createDeletingChange (Object id , @ Nullable T entity , Class <T > domainType ) {
331367
332- MutableAggregateChange <T > aggregateChange = MutableAggregateChange .forDelete (domainType , entity );
368+ Number previousVersion = null ;
369+ if (entity != null ) {
370+ RelationalPersistentEntity <T > persistentEntity = getRequiredPersistentEntity (entity );
371+ if (persistentEntity .hasVersionProperty ()) {
372+ previousVersion = RelationalEntityVersionUtils .getVersionNumberFromEntity (entity , persistentEntity , converter );
373+ }
374+ }
375+ MutableAggregateChange <T > aggregateChange = MutableAggregateChange .forDelete (domainType , entity , previousVersion );
333376jdbcEntityDeleteWriter .write (id , aggregateChange );
334377return aggregateChange ;
335378}
0 commit comments