Skip to content

Commit

Permalink
Dedicated exception for aggregate roots without id property.
Browse files Browse the repository at this point in the history
We now distinguish between an id not set during insert and a supposed aggregate root without id property.

Closes #1502
Original pull request #1855
  • Loading branch information
schauder committed Aug 14, 2024
1 parent 1c75679 commit 7e6f548
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,8 @@ public <T> T save(T instance) {

Assert.notNull(instance, "Aggregate instance must not be null");

verifyIdProperty(instance);

return performSave(new EntityAndChangeCreator<>(instance, changeCreatorSelectorForSave(instance)));
}

Expand All @@ -179,6 +181,7 @@ public <T> Iterable<T> saveAll(Iterable<T> instances) {

List<EntityAndChangeCreator<T>> entityAndChangeCreators = new ArrayList<>();
for (T instance : instances) {
verifyIdProperty(instance);
entityAndChangeCreators.add(new EntityAndChangeCreator<>(instance, changeCreatorSelectorForSave(instance)));
}
return performSaveAll(entityAndChangeCreators);
Expand Down Expand Up @@ -425,6 +428,11 @@ public <T> void deleteAll(Iterable<? extends T> instances) {
}
}

private <T> void verifyIdProperty(T instance) {
// accessing the id property just to raise an exception in the case it does not exist.
context.getRequiredPersistentEntity(instance.getClass()).getRequiredIdProperty();
}

private <T> void doDeleteAll(Iterable<? extends T> instances, Class<T> domainType) {

BatchingAggregateChange<T, DeleteAggregateChange<T>> batchingAggregateChange = BatchingAggregateChange
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,12 @@
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.jdbc.core.convert.DataAccessStrategy;
import org.springframework.data.jdbc.core.convert.Identifier;
import org.springframework.data.jdbc.core.convert.JdbcConverter;
import org.springframework.data.jdbc.core.convert.MappingJdbcConverter;
import org.springframework.data.jdbc.core.convert.RelationResolver;
import org.springframework.data.mapping.callback.EntityCallbacks;
import org.springframework.data.relational.core.conversion.IdValueSource;
import org.springframework.data.relational.core.conversion.MutableAggregateChange;
import org.springframework.data.relational.core.mapping.Column;
import org.springframework.data.relational.core.mapping.RelationalMappingContext;
Expand All @@ -46,6 +48,8 @@
import org.springframework.data.relational.core.mapping.event.BeforeDeleteCallback;
import org.springframework.data.relational.core.mapping.event.BeforeSaveCallback;

import java.util.List;

/**
* Unit tests for {@link JdbcAggregateTemplate}.
*
Expand Down Expand Up @@ -333,6 +337,38 @@ void deleteAllByIdWithEmptyListDoesNothing() {
template.deleteAllById(emptyList(), SampleEntity.class);
}

@Test // GH-1502
void saveThrowsExceptionWhenIdIsNotSet() {

SampleEntity alfred = new SampleEntity(null, "Alfred");
when(callbacks.callback(any(), any(), any(Object[].class))).thenReturn(alfred);

when(dataAccessStrategy.insert(eq(alfred), any(Class.class), any(Identifier.class), any(IdValueSource.class)))
.thenReturn(null);

assertThatIllegalArgumentException().isThrownBy(() -> template.save(alfred))
.withMessage("After saving the identifier must not be null");
}

@Test // GH-1502
void saveThrowsExceptionWhenIdDoesNotExist() {

NoIdEntity alfred = new NoIdEntity("Alfred");

assertThatIllegalStateException().isThrownBy(() -> template.save(alfred))
.withMessage("Required identifier property not found for class %s".formatted(NoIdEntity.class.getName()));
}

@Test // GH-1502
void saveThrowsExceptionWhenIdDoesNotExistOnSaveAll() {

NoIdEntity alfred = new NoIdEntity("Alfred");
NoIdEntity berta = new NoIdEntity("Berta");

assertThatIllegalStateException().isThrownBy(() -> template.saveAll( List.of(alfred, berta)))
.withMessage("Required identifier property not found for class %s".formatted(NoIdEntity.class.getName()));
}

private static class SampleEntity {

@Column("id1")
Expand Down Expand Up @@ -451,4 +487,7 @@ public long getVersion() {
return this.version;
}
}

record NoIdEntity(String name) {
}
}

0 comments on commit 7e6f548

Please sign in to comment.