Try to extend spring boot ReactiveCrudRepository
interface to have separate methods for entity insertion and updating. Right now save()
method differentiate insertion from updating checking ID is provided or not. The idea why I need extend it in this way because coming kafka events with new or modified entities already has filled ID.
CustomReactiveCrudRepository:
public interface CustomReactiveCrudRepository<T, ID> extends ReactiveCrudRepository<T, ID> {
<S extends T> Mono<S> insert(S entity);
<S extends T> Mono<S> update(S entity);
}
CustomReactiveCrudRepositoryImpl:
public class CustomReactiveCrudRepositoryImpl<T, ID> extends SimpleR2dbcRepository<T, ID> implements CustomReactiveCrudRepository<T, ID> {
private final RelationalEntityInformation<T, ID> entity;
private final DatabaseClient databaseClient;
public CustomReactiveCrudRepositoryImpl(RelationalEntityInformation<T, ID> entity, DatabaseClient databaseClient, R2dbcConverter converter, ReactiveDataAccessStrategy accessStrategy) {
super(entity, databaseClient, converter, accessStrategy);
this.entity = entity;
this.databaseClient = databaseClient;
}
@Override
public <S extends T> Mono<S> insert(S objectToSave) {
Assert.notNull(objectToSave, "Object to save must not be null!");
return this.databaseClient.insert()
.into(this.entity.getJavaType())
.table(this.entity.getTableName()).using(objectToSave)
// Removed ID generation since it's generated initially
.map((row, rowMetadata) -> objectToSave)
.first()
.defaultIfEmpty(objectToSave);
}
@Override
public <S extends T> Mono<S> update(S objectToSave) {
Assert.notNull(objectToSave, "Object to save must not be null!");
return this.databaseClient.update()
.table(this.entity.getJavaType())
.table(this.entity.getTableName()).using(objectToSave)
.fetch().rowsUpdated().handle((rowsUpdated, sink) -> {
if (rowsUpdated == 0) {
sink.error(new TransientDataAccessResourceException(
String.format("Failed to update table [%s]. Row with Id [%s] does not exist.",
this.entity.getTableName(), this.entity.getId(objectToSave))));
} else {
sink.next(objectToSave);
}
});
}
}
FooRepository:
@Repository
public interface FooRepository extends CustomReactiveCrudRepository<Foo, UUID> {}
Foo entity:
@Data
@Table
public class Foo {
@Id
private UUID id;
private SomeStatus someStatus;
private Boolean someBoolean;
}
The above example cause UnsupportedOperationException:
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'fooRepository': Invocation of init method failed; nested exception is java.lang.UnsupportedOperationException: Query derivation not yet supported!
How I should extend such functionality in proper way?