Skip to content

Commit a5238fa

Browse files
committed
Reestablish previous exception behavior.
When saving an Aggregate which is not new, but has a null version attribute we now throw a DbActionExecutionException, like we used to. Closes #1254
1 parent ac58399 commit a5238fa

File tree

2 files changed

+34
-12
lines changed

2 files changed

+34
-12
lines changed

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

+1-3
Original file line numberDiff line numberDiff line change
@@ -353,9 +353,7 @@ private <T> EntityAndPreviousVersion<T> prepareVersionForUpdate(T instance) {
353353
// If the root aggregate has a version property, increment it.
354354
previousVersion = RelationalEntityVersionUtils.getVersionNumberFromEntity(instance, persistentEntity, converter);
355355

356-
Assert.notNull(previousVersion, "The root aggregate cannot be updated because the version property is null.");
357-
358-
long newVersion = previousVersion.longValue() + 1;
356+
long newVersion = (previousVersion == null ? 0 : previousVersion.longValue()) + 1;
359357

360358
preparedInstance = RelationalEntityVersionUtils.setVersionNumberOnEntity(instance, newVersion, persistentEntity,
361359
converter);

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

+33-9
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353
import org.springframework.data.annotation.ReadOnlyProperty;
5454
import org.springframework.data.annotation.Version;
5555
import org.springframework.data.domain.PageRequest;
56+
import org.springframework.data.domain.Persistable;
5657
import org.springframework.data.domain.Sort;
5758
import org.springframework.data.jdbc.core.convert.DataAccessStrategy;
5859
import org.springframework.data.jdbc.core.convert.JdbcConverter;
@@ -258,14 +259,15 @@ void saveAndLoadManyEntitiesWithReferencedEntitySortedAndPaged() {
258259
}
259260

260261
@Test // GH-821
261-
@EnabledOnFeature({SUPPORTS_QUOTED_IDS, SUPPORTS_NULL_PRECEDENCE})
262+
@EnabledOnFeature({ SUPPORTS_QUOTED_IDS, SUPPORTS_NULL_PRECEDENCE })
262263
void saveAndLoadManyEntitiesWithReferencedEntitySortedWithNullPrecedence() {
263264

264265
template.save(createLegoSet(null));
265266
template.save(createLegoSet("Star"));
266267
template.save(createLegoSet("Frozen"));
267268

268-
Iterable<LegoSet> reloadedLegoSets = template.findAll(LegoSet.class, Sort.by(new Sort.Order(Sort.Direction.ASC, "name", Sort.NullHandling.NULLS_LAST)));
269+
Iterable<LegoSet> reloadedLegoSets = template.findAll(LegoSet.class,
270+
Sort.by(new Sort.Order(Sort.Direction.ASC, "name", Sort.NullHandling.NULLS_LAST)));
269271

270272
assertThat(reloadedLegoSets) //
271273
.extracting("name") //
@@ -843,7 +845,8 @@ void testUpdateEntityWithVersionDoesNotTriggerAnewConstructorInvocation() {
843845
assertThat(updatedRoot.version).isEqualTo(1L);
844846

845847
// Expect only one assignment of the version to AggregateWithImmutableVersion
846-
assertThat(AggregateWithImmutableVersion.constructorInvocations).containsOnly(new ConstructorInvocation(savedRoot.id, updatedRoot.version));
848+
assertThat(AggregateWithImmutableVersion.constructorInvocations)
849+
.containsOnly(new ConstructorInvocation(savedRoot.id, updatedRoot.version));
847850
}
848851

849852
@Test // DATAJDBC-219 Test that a delete with a version attribute works as expected.
@@ -908,6 +911,16 @@ void saveAndUpdateAggregateWithPrimitiveShortVersion() {
908911
saveAndUpdateAggregateWithPrimitiveVersion(new AggregateWithPrimitiveShortVersion(), Number::shortValue);
909912
}
910913

914+
@Test // GH-1254
915+
void saveAndUpdateAggregateWithIdAndNullVersion() {
916+
917+
PersistableVersionedAggregate aggregate = new PersistableVersionedAggregate();
918+
aggregate.setVersion(null);
919+
aggregate.setId(23L);
920+
921+
assertThatThrownBy(() -> template.save(aggregate)).isInstanceOf(DbActionExecutionException.class);
922+
}
923+
911924
@Test // DATAJDBC-462
912925
@EnabledOnFeature(SUPPORTS_QUOTED_IDS)
913926
void resavingAnUnversionedEntity() {
@@ -1075,18 +1088,15 @@ static class ListParent {
10751088

10761089
@Column("id4") @Id private Long id;
10771090
String name;
1078-
@MappedCollection(idColumn = "LIST_PARENT")
1079-
List<ElementNoId> content = new ArrayList<>();
1091+
@MappedCollection(idColumn = "LIST_PARENT") List<ElementNoId> content = new ArrayList<>();
10801092
}
10811093

10821094
@Table("LIST_PARENT")
10831095
static class ListParentAllArgs {
10841096

1085-
@Column("id4") @Id
1086-
private final Long id;
1097+
@Column("id4") @Id private final Long id;
10871098
private final String name;
1088-
@MappedCollection(idColumn = "LIST_PARENT")
1089-
private final List<ElementNoId> content = new ArrayList<>();
1099+
@MappedCollection(idColumn = "LIST_PARENT") private final List<ElementNoId> content = new ArrayList<>();
10901100

10911101
@PersistenceConstructor
10921102
ListParentAllArgs(Long id, String name, List<ElementNoId> content) {
@@ -1247,6 +1257,20 @@ static abstract class VersionedAggregate {
12471257
abstract void setVersion(Number newVersion);
12481258
}
12491259

1260+
@Data
1261+
@Table("VERSIONED_AGGREGATE")
1262+
static class PersistableVersionedAggregate implements Persistable<Long> {
1263+
1264+
@Id private Long id;
1265+
1266+
@Version Long version;
1267+
1268+
@Override
1269+
public boolean isNew() {
1270+
return getId() == null;
1271+
}
1272+
}
1273+
12501274
@Value
12511275
@With
12521276
@Table("VERSIONED_AGGREGATE")

0 commit comments

Comments
 (0)