From 9e8d4420d405c0b8c4c444b145ef9d0ac84f3ffe Mon Sep 17 00:00:00 2001 From: AndreynRosa Date: Fri, 26 Jul 2024 06:43:56 -0300 Subject: [PATCH 1/3] fix: exception when a agregate root no have id --- .../data/jdbc/core/JdbcAggregateTemplate.java | 43 +++++++++++-------- .../core/JdbcAggregateTemplateUnitTests.java | 34 +++++++++++++++ 2 files changed, 60 insertions(+), 17 deletions(-) diff --git a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/JdbcAggregateTemplate.java b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/JdbcAggregateTemplate.java index efa04a8d8b..7466f4300d 100644 --- a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/JdbcAggregateTemplate.java +++ b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/JdbcAggregateTemplate.java @@ -22,6 +22,7 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Optional; import java.util.function.Function; import java.util.stream.Collectors; @@ -67,6 +68,7 @@ * @author Myeonghyeon Lee * @author Chirag Tailor * @author Diego Krupitza + * @author Andrey Rosa */ public class JdbcAggregateTemplate implements JdbcAggregateOperations { @@ -85,13 +87,13 @@ public class JdbcAggregateTemplate implements JdbcAggregateOperations { * Creates a new {@link JdbcAggregateTemplate} given {@link ApplicationContext}, {@link RelationalMappingContext} and * {@link DataAccessStrategy}. * - * @param publisher must not be {@literal null}. - * @param context must not be {@literal null}. + * @param publisher must not be {@literal null}. + * @param context must not be {@literal null}. * @param dataAccessStrategy must not be {@literal null}. * @since 1.1 */ public JdbcAggregateTemplate(ApplicationContext publisher, RelationalMappingContext context, JdbcConverter converter, - DataAccessStrategy dataAccessStrategy) { + DataAccessStrategy dataAccessStrategy) { Assert.notNull(publisher, "ApplicationContext must not be null"); Assert.notNull(context, "RelationalMappingContext must not be null"); @@ -114,12 +116,12 @@ public JdbcAggregateTemplate(ApplicationContext publisher, RelationalMappingCont * Creates a new {@link JdbcAggregateTemplate} given {@link ApplicationEventPublisher}, * {@link RelationalMappingContext} and {@link DataAccessStrategy}. * - * @param publisher must not be {@literal null}. - * @param context must not be {@literal null}. + * @param publisher must not be {@literal null}. + * @param context must not be {@literal null}. * @param dataAccessStrategy must not be {@literal null}. */ public JdbcAggregateTemplate(ApplicationEventPublisher publisher, RelationalMappingContext context, - JdbcConverter converter, DataAccessStrategy dataAccessStrategy) { + JdbcConverter converter, DataAccessStrategy dataAccessStrategy) { Assert.notNull(publisher, "ApplicationEventPublisher must not be null"); Assert.notNull(context, "RelationalMappingContext must not be null"); @@ -153,8 +155,8 @@ public void setEntityCallbacks(EntityCallbacks entityCallbacks) { * published or whether emission should be suppressed. Enabled by default. * * @param enabled {@code true} to enable entity lifecycle events; {@code false} to disable entity lifecycle events. - * @since 3.0 * @see AbstractRelationalEvent + * @since 3.0 */ public void setEntityLifecycleEventsEnabled(boolean enabled) { this.eventDelegate.setEventsEnabled(enabled); @@ -447,11 +449,6 @@ private void doDeleteAll(Iterable instances, Class domainTyp private T afterExecute(AggregateChange change, T entityAfterExecution) { - Object identifier = context.getRequiredPersistentEntity(change.getEntityType()) - .getIdentifierAccessor(entityAfterExecution).getIdentifier(); - - Assert.notNull(identifier, "After saving the identifier must not be null"); - return triggerAfterSave(entityAfterExecution, change); } @@ -482,7 +479,6 @@ private void deleteTree(Object id, @Nullable T entity, Class domainType) } private T performSave(EntityAndChangeCreator instance) { - // noinspection unchecked BatchingAggregateChange> batchingAggregateChange = // BatchingAggregateChange.forSave((Class) ClassUtils.getUserClass(instance.entity)); @@ -492,7 +488,10 @@ private T performSave(EntityAndChangeCreator instance) { Assert.isTrue(afterExecutionIterator.hasNext(), "Instances after execution must not be empty"); - return afterExecute(batchingAggregateChange, afterExecutionIterator.next()); + T afterExecute = afterExecutionIterator.next(); + checkIfHaveId(context.getRequiredPersistentEntity(batchingAggregateChange.getEntityType()) + .getIdentifierAccessor(afterExecute)); + return afterExecute(batchingAggregateChange, afterExecute); } private List performSaveAll(Iterable> instances) { @@ -513,12 +512,22 @@ private List performSaveAll(Iterable> instances ArrayList results = new ArrayList<>(instancesAfterExecution.size()); for (T instance : instancesAfterExecution) { - results.add(afterExecute(batchingAggregateChange, instance)); + T afterExecuteElement = afterExecute(batchingAggregateChange, instance); + checkIfHaveId(context.getRequiredPersistentEntity(batchingAggregateChange.getEntityType()) + .getIdentifierAccessor(afterExecuteElement)); + results.add(afterExecuteElement); } return results; } + private void checkIfHaveId(IdentifierAccessor context) { + Object identifier = context.getIdentifier(); + if (Objects.isNull(identifier)) { + throw new IllegalStateException("After saving the identifier must not be null"); + } + } + private Function> changeCreatorSelectorForSave(T instance) { return context.getRequiredPersistentEntity(instance.getClass()).isNew(instance) @@ -656,9 +665,9 @@ private T triggerBeforeDelete(@Nullable T aggregateRoot, Object id, MutableA return null; } - private record EntityAndPreviousVersion (T entity, @Nullable Number version) { + private record EntityAndPreviousVersion(T entity, @Nullable Number version) { } - private record EntityAndChangeCreator (T entity, Function> changeCreator) { + private record EntityAndChangeCreator(T entity, Function> changeCreator) { } } diff --git a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/JdbcAggregateTemplateUnitTests.java b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/JdbcAggregateTemplateUnitTests.java index d9e6ed3368..5eab6fc64a 100644 --- a/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/JdbcAggregateTemplateUnitTests.java +++ b/spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/JdbcAggregateTemplateUnitTests.java @@ -18,6 +18,8 @@ import static java.util.Arrays.*; import static java.util.Collections.*; import static org.assertj.core.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.Mockito.*; import org.junit.jupiter.api.BeforeEach; @@ -53,6 +55,7 @@ * @author Mark Paluch * @author Milan Milanov * @author Chirag Tailor + * @author Andrey Rosa */ @ExtendWith(MockitoExtension.class) public class JdbcAggregateTemplateUnitTests { @@ -161,6 +164,18 @@ void savePreparesInstanceWithInitialVersion_onInsert_whenVersionPropertyIsImmuta assertThat(afterConvert.getVersion()).isEqualTo(0L); } + @Test + // GH-1502 + void savePreparesInstanceWithoutIdentifier() { + + EntityWitoutId entity = new EntityWitoutId(); + when(callbacks.callback(any(), any(), any(Object[].class))).thenReturn(entity, entity); + + IllegalStateException exception = assertThrows(IllegalStateException.class, () -> { + template.save(entity); + }); + assertEquals("After saving the identifier must not be null", exception.getMessage()); + } @Test // GH-1137 void savePreparesInstanceWithInitialVersion_onInsert_whenVersionPropertyIsPrimitiveType() { @@ -423,7 +438,26 @@ public Long getVersion() { return this.version; } } + private static class EntityWitoutId { + + + @Version + private long version; + + public EntityWitoutId() { + + } + + + + public long getVersion() { + return this.version; + } + public void setVersion(long version) { + this.version = version; + } + } private static class EntityWithPrimitiveVersion { @Column("id1") From 44effa3e60d40cc2f341976a15588e8f2ab02aeb Mon Sep 17 00:00:00 2001 From: AndreynRosa Date: Sat, 27 Jul 2024 10:18:27 -0300 Subject: [PATCH 2/3] fix code formmater --- .../data/jdbc/core/JdbcAggregateTemplate.java | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/JdbcAggregateTemplate.java b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/JdbcAggregateTemplate.java index 7466f4300d..f6a1c3c543 100644 --- a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/JdbcAggregateTemplate.java +++ b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/JdbcAggregateTemplate.java @@ -87,13 +87,12 @@ public class JdbcAggregateTemplate implements JdbcAggregateOperations { * Creates a new {@link JdbcAggregateTemplate} given {@link ApplicationContext}, {@link RelationalMappingContext} and * {@link DataAccessStrategy}. * - * @param publisher must not be {@literal null}. - * @param context must not be {@literal null}. + * @param publisher must not be {@literal null}. + * @param context must not be {@literal null}. * @param dataAccessStrategy must not be {@literal null}. * @since 1.1 */ - public JdbcAggregateTemplate(ApplicationContext publisher, RelationalMappingContext context, JdbcConverter converter, - DataAccessStrategy dataAccessStrategy) { + . Assert.notNull(publisher, "ApplicationContext must not be null"); Assert.notNull(context, "RelationalMappingContext must not be null"); @@ -116,12 +115,12 @@ public JdbcAggregateTemplate(ApplicationContext publisher, RelationalMappingCont * Creates a new {@link JdbcAggregateTemplate} given {@link ApplicationEventPublisher}, * {@link RelationalMappingContext} and {@link DataAccessStrategy}. * - * @param publisher must not be {@literal null}. - * @param context must not be {@literal null}. + * @param publisher must not be {@literal null}. + * @param context must not be {@literal null}. * @param dataAccessStrategy must not be {@literal null}. */ public JdbcAggregateTemplate(ApplicationEventPublisher publisher, RelationalMappingContext context, - JdbcConverter converter, DataAccessStrategy dataAccessStrategy) { + JdbcConverter converter, DataAccessStrategy dataAccessStrategy) { Assert.notNull(publisher, "ApplicationEventPublisher must not be null"); Assert.notNull(context, "RelationalMappingContext must not be null"); From 6be2c8d52ca3ed756ed997d4bbedb282155e1849 Mon Sep 17 00:00:00 2001 From: AndreynRosa Date: Sat, 27 Jul 2024 10:22:44 -0300 Subject: [PATCH 3/3] fix code formmater --- .../springframework/data/jdbc/core/JdbcAggregateTemplate.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/JdbcAggregateTemplate.java b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/JdbcAggregateTemplate.java index f6a1c3c543..dcdc348437 100644 --- a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/JdbcAggregateTemplate.java +++ b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/JdbcAggregateTemplate.java @@ -92,7 +92,8 @@ public class JdbcAggregateTemplate implements JdbcAggregateOperations { * @param dataAccessStrategy must not be {@literal null}. * @since 1.1 */ - . + public JdbcAggregateTemplate(ApplicationContext publisher, RelationalMappingContext context, JdbcConverter converter, + DataAccessStrategy dataAccessStrategy) { Assert.notNull(publisher, "ApplicationContext must not be null"); Assert.notNull(context, "RelationalMappingContext must not be null");