Skip to content

Commit fe313a9

Browse files
committed
#215 - Polishing.
Reintroduce deprecated setBeanFactory(…) method. Extract code into methods. Ensure that versioned entities are eagerly initialized to allow retries.
1 parent 47c2626 commit fe313a9

File tree

1 file changed

+82
-54
lines changed

1 file changed

+82
-54
lines changed

src/main/java/org/springframework/data/r2dbc/core/R2dbcEntityTemplate.java

+82-54
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@
3232
import org.reactivestreams.Publisher;
3333

3434
import org.springframework.beans.BeansException;
35+
import org.springframework.beans.factory.BeanFactory;
36+
import org.springframework.beans.factory.BeanFactoryAware;
3537
import org.springframework.context.ApplicationContext;
3638
import org.springframework.context.ApplicationContextAware;
3739
import org.springframework.core.convert.ConversionService;
@@ -77,7 +79,7 @@
7779
* @author Bogdan Ilchyshyn
7880
* @since 1.1
7981
*/
80-
public class R2dbcEntityTemplate implements R2dbcEntityOperations, ApplicationContextAware {
82+
public class R2dbcEntityTemplate implements R2dbcEntityOperations, BeanFactoryAware, ApplicationContextAware {
8183

8284
private final DatabaseClient databaseClient;
8385

@@ -123,6 +125,15 @@ public DatabaseClient getDatabaseClient() {
123125
return this.databaseClient;
124126
}
125127

128+
/*
129+
* (non-Javadoc)
130+
* @see org.springframework.beans.factory.BeanFactoryAware#setBeanFactory(org.springframework.beans.factory.BeanFactory)
131+
* @deprecated since 1.2 in favor of #setApplicationContext.
132+
*/
133+
@Override
134+
@Deprecated
135+
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {}
136+
126137
/*
127138
* (non-Javadoc)
128139
* @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext)
@@ -431,33 +442,38 @@ <T> Mono<T> doInsert(T entity, SqlIdentifier tableName) {
431442

432443
RelationalPersistentEntity<T> persistentEntity = getRequiredEntity(entity);
433444

434-
return Mono.defer(() -> maybeCallBeforeConvert(setVersionIfNecessary(persistentEntity, entity), tableName)
445+
T entityWithVersion = setVersionIfNecessary(persistentEntity, entity);
446+
447+
return maybeCallBeforeConvert(entityWithVersion, tableName)
435448
.flatMap(beforeConvert -> {
436449

437450
OutboundRow outboundRow = dataAccessStrategy.getOutboundRow(beforeConvert);
438451

439-
return maybeCallBeforeSave(beforeConvert, outboundRow, tableName).flatMap(entityToSave -> {
452+
return maybeCallBeforeSave(beforeConvert, outboundRow, tableName) //
453+
.flatMap(entityToSave -> doInsert(entityToSave, tableName, outboundRow));
454+
});
455+
}
456+
457+
private <T> Mono<T> doInsert(T entity, SqlIdentifier tableName, OutboundRow outboundRow) {
440458

441-
StatementMapper mapper = dataAccessStrategy.getStatementMapper();
442-
StatementMapper.InsertSpec insert = mapper.createInsert(tableName);
459+
StatementMapper mapper = dataAccessStrategy.getStatementMapper();
460+
StatementMapper.InsertSpec insert = mapper.createInsert(tableName);
443461

444-
for (SqlIdentifier column : outboundRow.keySet()) {
445-
SettableValue settableValue = outboundRow.get(column);
446-
if (settableValue.hasValue()) {
447-
insert = insert.withColumn(column, settableValue);
448-
}
449-
}
462+
for (SqlIdentifier column : outboundRow.keySet()) {
463+
SettableValue settableValue = outboundRow.get(column);
464+
if (settableValue.hasValue()) {
465+
insert = insert.withColumn(column, settableValue);
466+
}
467+
}
450468

451-
PreparedOperation<?> operation = mapper.getMappedObject(insert);
469+
PreparedOperation<?> operation = mapper.getMappedObject(insert);
452470

453-
return this.databaseClient.execute(operation) //
454-
.filter(statement -> statement.returnGeneratedValues())
455-
.map(this.dataAccessStrategy.getConverter().populateIdIfNecessary(entityToSave)) //
456-
.first() //
457-
.defaultIfEmpty(entityToSave) //
458-
.flatMap(saved -> maybeCallAfterSave(saved, outboundRow, tableName));
459-
});
460-
}));
471+
return this.databaseClient.execute(operation) //
472+
.filter(statement -> statement.returnGeneratedValues())
473+
.map(this.dataAccessStrategy.getConverter().populateIdIfNecessary(entity)) //
474+
.first() //
475+
.defaultIfEmpty(entity) //
476+
.flatMap(saved -> maybeCallAfterSave(saved, outboundRow, tableName));
461477
}
462478

463479
@SuppressWarnings("unchecked")
@@ -493,9 +509,22 @@ private <T> Mono<T> doUpdate(T entity, SqlIdentifier tableName) {
493509

494510
RelationalPersistentEntity<T> persistentEntity = getRequiredEntity(entity);
495511

496-
return maybeCallBeforeConvert(entity, tableName).flatMap(beforeConvert -> {
512+
T entityToUse;
513+
Criteria matchingVersionCriteria;
514+
515+
if (persistentEntity.hasVersionProperty()) {
497516

498-
OutboundRow outboundRow = dataAccessStrategy.getOutboundRow(entity);
517+
matchingVersionCriteria = createMatchingVersionCriteria(entity, persistentEntity);
518+
entityToUse = incrementVersion(persistentEntity, entity);
519+
} else {
520+
521+
entityToUse = entity;
522+
matchingVersionCriteria = null;
523+
}
524+
525+
return maybeCallBeforeConvert(entityToUse, tableName).flatMap(beforeConvert -> {
526+
527+
OutboundRow outboundRow = dataAccessStrategy.getOutboundRow(beforeConvert);
499528

500529
return maybeCallBeforeSave(beforeConvert, outboundRow, tableName) //
501530
.flatMap(entityToSave -> {
@@ -504,43 +533,44 @@ private <T> Mono<T> doUpdate(T entity, SqlIdentifier tableName) {
504533
SettableValue id = outboundRow.remove(idColumn);
505534
Criteria criteria = Criteria.where(dataAccessStrategy.toSql(idColumn)).is(id);
506535

507-
T saved;
508-
509-
if (persistentEntity.hasVersionProperty()) {
510-
criteria = criteria.and(createMatchingVersionCriteria(entity, persistentEntity));
511-
saved = incrementVersion(persistentEntity, entity, outboundRow);
512-
} else {
513-
saved = entityToSave;
536+
if (matchingVersionCriteria != null) {
537+
criteria = criteria.and(matchingVersionCriteria);
514538
}
515539

516-
Update update = Update.from((Map) outboundRow);
540+
return doUpdate(entityToSave, tableName, persistentEntity, criteria, outboundRow);
541+
});
542+
});
543+
}
544+
545+
@SuppressWarnings({ "unchecked", "rawtypes" })
546+
private <T> Mono<T> doUpdate(T entity, SqlIdentifier tableName, RelationalPersistentEntity<T> persistentEntity,
547+
Criteria criteria, OutboundRow outboundRow) {
517548

518-
StatementMapper mapper = dataAccessStrategy.getStatementMapper();
519-
StatementMapper.UpdateSpec updateSpec = mapper.createUpdate(tableName, update).withCriteria(criteria);
549+
Update update = Update.from((Map) outboundRow);
520550

521-
PreparedOperation<?> operation = mapper.getMappedObject(updateSpec);
551+
StatementMapper mapper = dataAccessStrategy.getStatementMapper();
552+
StatementMapper.UpdateSpec updateSpec = mapper.createUpdate(tableName, update).withCriteria(criteria);
522553

523-
return this.databaseClient.execute(operation) //
524-
.fetch() //
525-
.rowsUpdated() //
526-
.handle((rowsUpdated, sink) -> {
554+
PreparedOperation<?> operation = mapper.getMappedObject(updateSpec);
527555

528-
if (rowsUpdated != 0) {
529-
return;
530-
}
556+
return this.databaseClient.execute(operation) //
557+
.fetch() //
558+
.rowsUpdated() //
559+
.handle((rowsUpdated, sink) -> {
531560

532-
if (persistentEntity.hasVersionProperty()) {
533-
sink.error(new OptimisticLockingFailureException(
534-
formatOptimisticLockingExceptionMessage(saved, persistentEntity)));
535-
} else {
536-
sink.error(new TransientDataAccessResourceException(
537-
formatTransientEntityExceptionMessage(saved, persistentEntity)));
538-
}
539-
}).then(maybeCallAfterSave(saved, outboundRow, tableName));
540-
});
541-
});
542-
}
561+
if (rowsUpdated != 0) {
562+
return;
563+
}
543564

565+
if (persistentEntity.hasVersionProperty()) {
566+
sink.error(new OptimisticLockingFailureException(
567+
formatOptimisticLockingExceptionMessage(entity, persistentEntity)));
568+
} else {
569+
sink.error(new TransientDataAccessResourceException(
570+
formatTransientEntityExceptionMessage(entity, persistentEntity)));
571+
}
572+
}).then(maybeCallAfterSave(entity, outboundRow, tableName));
573+
}
544574

545575
private <T> String formatOptimisticLockingExceptionMessage(T entity, RelationalPersistentEntity<T> persistentEntity) {
546576

@@ -555,7 +585,7 @@ private <T> String formatTransientEntityExceptionMessage(T entity, RelationalPer
555585
}
556586

557587
@SuppressWarnings("unchecked")
558-
private <T> T incrementVersion(RelationalPersistentEntity<T> persistentEntity, T entity, OutboundRow outboundRow) {
588+
private <T> T incrementVersion(RelationalPersistentEntity<T> persistentEntity, T entity) {
559589

560590
PersistentPropertyAccessor<?> propertyAccessor = persistentEntity.getPropertyAccessor(entity);
561591
RelationalPersistentProperty versionProperty = persistentEntity.getVersionProperty();
@@ -569,8 +599,6 @@ private <T> T incrementVersion(RelationalPersistentEntity<T> persistentEntity, T
569599
Class<?> versionPropertyType = versionProperty.getType();
570600
propertyAccessor.setProperty(versionProperty, conversionService.convert(newVersionValue, versionPropertyType));
571601

572-
outboundRow.put(versionProperty.getColumnName(), SettableValue.from(newVersionValue));
573-
574602
return (T) propertyAccessor.getBean();
575603
}
576604

0 commit comments

Comments
 (0)