|
26 | 26 | import java.util.stream.Collectors;
|
27 | 27 | import java.util.stream.StreamSupport;
|
28 | 28 |
|
| 29 | +import org.springframework.core.convert.ConversionService; |
29 | 30 | import org.springframework.dao.DataRetrievalFailureException;
|
30 | 31 | import org.springframework.dao.EmptyResultDataAccessException;
|
31 | 32 | import org.springframework.dao.InvalidDataAccessApiUsageException;
|
|
34 | 35 | import org.springframework.data.mapping.PersistentPropertyAccessor;
|
35 | 36 | import org.springframework.data.mapping.PersistentPropertyPath;
|
36 | 37 | import org.springframework.data.mapping.PropertyHandler;
|
| 38 | +import org.springframework.data.mapping.model.ConvertingPropertyAccessor; |
37 | 39 | import org.springframework.data.relational.core.conversion.RelationalConverter;
|
38 | 40 | import org.springframework.data.relational.core.mapping.RelationalMappingContext;
|
39 | 41 | import org.springframework.data.relational.core.mapping.RelationalPersistentEntity;
|
@@ -71,7 +73,7 @@ public class DefaultDataAccessStrategy implements DataAccessStrategy {
|
71 | 73 | * Only suitable if this is the only access strategy in use.
|
72 | 74 | */
|
73 | 75 | public DefaultDataAccessStrategy(SqlGeneratorSource sqlGeneratorSource, RelationalMappingContext context,
|
74 |
| - RelationalConverter converter, NamedParameterJdbcOperations operations) { |
| 76 | + RelationalConverter converter, NamedParameterJdbcOperations operations) { |
75 | 77 |
|
76 | 78 | this.sqlGeneratorSource = sqlGeneratorSource;
|
77 | 79 | this.operations = operations;
|
@@ -117,9 +119,9 @@ public <T> Object insert(T instance, Class<T> domainType, Identifier identifier)
|
117 | 119 | }
|
118 | 120 |
|
119 | 121 | if (persistentEntity.hasVersionProperty()) {
|
120 |
| - VersionAccessor versionAccessor = new VersionAccessor<>(instance, persistentEntity); |
121 |
| - Number newVersion = versionAccessor.nextVersion(); |
122 |
| - versionAccessor.setVersion(newVersion); |
| 122 | + |
| 123 | + Number newVersion = getNextVersion(instance, persistentEntity, converter.getConversionService()); |
| 124 | + setVersion(instance, persistentEntity, newVersion); |
123 | 125 | parameters.put(persistentEntity.getVersionProperty().getColumnName(), converter.writeValue(newVersion,
|
124 | 126 | ClassTypeInformation.from(persistentEntity.getVersionProperty().getColumnType())));
|
125 | 127 | }
|
@@ -159,18 +161,17 @@ private <S> boolean updateWithoutVersion(S instance, Class<S> domainType) {
|
159 | 161 | private <S> boolean updateWithVersion(S instance, Class<S> domainType) {
|
160 | 162 |
|
161 | 163 | RelationalPersistentEntity<S> persistentEntity = getRequiredPersistentEntity(domainType);
|
162 |
| - VersionAccessor<S> versionAccessor = new VersionAccessor<>(instance, persistentEntity); |
163 | 164 |
|
164 |
| - Number oldVersion = versionAccessor.currentVersion(); |
165 |
| - Number newVersion = versionAccessor.nextVersion(); |
166 |
| - versionAccessor.setVersion(newVersion); |
| 165 | + Number oldVersion = getVersion(instance, persistentEntity, converter.getConversionService()); |
| 166 | + Number newVersion = getNextVersion(instance, persistentEntity, converter.getConversionService()); |
| 167 | + setVersion(instance, persistentEntity, newVersion); |
167 | 168 |
|
168 | 169 | int affectedRows = operations.update(sql(domainType).getUpdateWithVersion(oldVersion),
|
169 | 170 | getPropertyMap(instance, persistentEntity, ""));
|
170 | 171 |
|
171 | 172 | if (affectedRows == 0) {
|
172 | 173 | // reverting version update on entity
|
173 |
| - versionAccessor.setVersion(oldVersion); |
| 174 | + setVersion(instance, persistentEntity, oldVersion); |
174 | 175 | throw new OptimisticLockingFailureException(
|
175 | 176 | String.format("Optimistic lock exception on saving entity of type %s.", persistentEntity.getName()));
|
176 | 177 | }
|
@@ -333,7 +334,7 @@ public <T> boolean existsById(Object id, Class<T> domainType) {
|
333 | 334 | }
|
334 | 335 |
|
335 | 336 | private <S, T> MapSqlParameterSource getPropertyMap(S instance, RelationalPersistentEntity<S> persistentEntity,
|
336 |
| - String prefix) { |
| 337 | + String prefix) { |
337 | 338 |
|
338 | 339 | MapSqlParameterSource parameters = new MapSqlParameterSource();
|
339 | 340 |
|
@@ -396,7 +397,7 @@ private <S, ID> ID getIdValueOrNull(S instance, RelationalPersistentEntity<S> pe
|
396 | 397 | }
|
397 | 398 |
|
398 | 399 | private static <S, ID> boolean isIdPropertyNullOrScalarZero(@Nullable ID idValue,
|
399 |
| - RelationalPersistentEntity<S> persistentEntity) { |
| 400 | + RelationalPersistentEntity<S> persistentEntity) { |
400 | 401 |
|
401 | 402 | RelationalPersistentProperty idProperty = persistentEntity.getIdProperty();
|
402 | 403 | return idValue == null //
|
@@ -452,4 +453,31 @@ private SqlGenerator sql(Class<?> domainType) {
|
452 | 453 | return sqlGeneratorSource.getSqlGenerator(domainType);
|
453 | 454 | }
|
454 | 455 |
|
| 456 | + @Nullable |
| 457 | + private <T> Number getVersion(T instance, RelationalPersistentEntity<T> entity, ConversionService conversionService) { |
| 458 | + RelationalPersistentProperty versionProperty = entity.getRequiredVersionProperty(); |
| 459 | + PersistentPropertyAccessor<T> propertyAccessor = entity.getPropertyAccessor(instance); |
| 460 | + ConvertingPropertyAccessor<T> convertingPropertyAccessor = new ConvertingPropertyAccessor<>(propertyAccessor, conversionService); |
| 461 | + return convertingPropertyAccessor.getProperty(versionProperty, Number.class); |
| 462 | + } |
| 463 | + |
| 464 | + private <T> Number getNextVersion(T instance, RelationalPersistentEntity<T> entity, ConversionService conversionService) { |
| 465 | + Number version = getVersion(instance, entity, conversionService); |
| 466 | + Class<?> versionType = entity.getRequiredVersionProperty().getType(); |
| 467 | + if (versionType == Integer.class || versionType == int.class) { |
| 468 | + return version == null ? 1 : version.intValue() + 1; |
| 469 | + } else if (versionType == Long.class || versionType == long.class) { |
| 470 | + return version == null ? 1L : version.longValue() + 1; |
| 471 | + } else if (versionType == Short.class || versionType == short.class) { |
| 472 | + return version == null ? (short) 1 : (short) (version.shortValue() + 1); |
| 473 | + } |
| 474 | + throw new IllegalStateException(String.format("Entity '%s' has version property of invalid type '%s'.", entity.getType().getName(), entity.getVersionProperty().getType().getName())); |
| 475 | + } |
| 476 | + |
| 477 | + private <T> void setVersion(T instance, RelationalPersistentEntity<T> entity, Number newVersion) { |
| 478 | + RelationalPersistentProperty versionProperty = entity.getRequiredVersionProperty(); |
| 479 | + PersistentPropertyAccessor<T> accessor = versionProperty.getOwner().getPropertyAccessor(instance); |
| 480 | + accessor.setProperty(versionProperty, newVersion); |
| 481 | + } |
| 482 | + |
455 | 483 | }
|
0 commit comments