1

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?

Viktor M.
  • 4,393
  • 9
  • 40
  • 71

2 Answers2

0

It might be not relevant anymore, but here is how I did it (with Spring webflux):

I am using R2dbc, which is creating a SimpleR2dbcRepository for every repository.

I created a custom class, which extended the SimpleR2dbcRepository called CustomRepository. And at a configuration I said @EnableR2dbcRepositories(repositoryBaseClass = CustomRepository.class)

Then I could override old methods and create new ones.

Dharman
  • 30,962
  • 25
  • 85
  • 135
iron24
  • 101
  • 1
  • 4
  • 19
  • And of course, you still need your custom interface, for your repository, so the method call is available. – iron24 Dec 29 '20 at 15:52
0

make sure you are importing org.springframework.data.r2dbc.repository.query.Query not org.springframework.data.jpa.repository.Query

cosbor11
  • 14,709
  • 10
  • 54
  • 69