From 4da92bdc7cd845ed772e70322993cdc80e9350ce Mon Sep 17 00:00:00 2001 From: Stephen Cohen Date: Tue, 21 Jul 2020 20:12:33 -0400 Subject: [PATCH] #407 - Add ReactiveSortingRepository support. Implements ReactiveSortingRepository on SimpleR2dbcRepository. Also changed R2dbcRepository to extend ReactiveSortingRepository and updated comments where it felt reasonable. Added a single unit test for the new method, and changed the base interface of LegoSetRepository in AbstractR2dbcRepositoryIntegrationTests for integration testing purposes. Clarify documentation on reactive repository base interfaces Adds some language calling out ReactiveSortingRepository and fixes consistency between related examples. Original pull request: #408. --- .../reference/r2dbc-repositories.adoc | 7 +++--- .../r2dbc/repository/R2dbcRepository.java | 5 +++-- .../support/R2dbcRepositoryFactoryBean.java | 2 +- .../support/SimpleR2dbcRepository.java | 16 +++++++++++--- ...stractR2dbcRepositoryIntegrationTests.java | 5 +++-- ...SimpleR2dbcRepositoryIntegrationTests.java | 22 +++++++++++++++++++ 6 files changed, 46 insertions(+), 11 deletions(-) diff --git a/src/main/asciidoc/reference/r2dbc-repositories.adoc b/src/main/asciidoc/reference/r2dbc-repositories.adoc index 03a28d78..9fcb8d7d 100644 --- a/src/main/asciidoc/reference/r2dbc-repositories.adoc +++ b/src/main/asciidoc/reference/r2dbc-repositories.adoc @@ -35,7 +35,7 @@ The following example shows a repository interface for the preceding `Person` cl ==== [source] ---- -public interface PersonRepository extends PagingAndSortingRepository { +public interface PersonRepository extends ReactiveCrudRepository { // additional custom query methods go here } @@ -62,7 +62,8 @@ class ApplicationConfig extends AbstractR2dbcConfiguration { ---- ==== -Because our domain repository extends `ReactiveCrudRepository`, it provides you with CRUD operations to access the entities. +Because our domain repository extends `ReactiveCrudRepository`, it provides you with reactive CRUD operations to access the entities. +On top of `ReactiveCrudRepository`, there is also `ReactiveSortingRepository`, which adds additional sorting functionality similar to that of `PagingAndSortingRepository`. Working with the repository instance is merely a matter of dependency injecting it into a client. Consequently, you can retrieve all `Person` objects with the following code: @@ -111,7 +112,7 @@ Defining such a query is a matter of declaring a method on the repository interf ==== [source,java] ---- -interface ReactivePersonRepository extends ReactiveSortingRepository { +interface ReactivePersonRepository extends ReactiveSortingRepository { Flux findByFirstname(String firstname); <1> diff --git a/src/main/java/org/springframework/data/r2dbc/repository/R2dbcRepository.java b/src/main/java/org/springframework/data/r2dbc/repository/R2dbcRepository.java index 63317fa7..8891d5b6 100644 --- a/src/main/java/org/springframework/data/r2dbc/repository/R2dbcRepository.java +++ b/src/main/java/org/springframework/data/r2dbc/repository/R2dbcRepository.java @@ -16,12 +16,13 @@ package org.springframework.data.r2dbc.repository; import org.springframework.data.repository.NoRepositoryBean; -import org.springframework.data.repository.reactive.ReactiveCrudRepository; +import org.springframework.data.repository.reactive.ReactiveSortingRepository; /** * R2DBC specific {@link org.springframework.data.repository.Repository} interface with reactive support. * * @author Mark Paluch + * @author Stephen Cohen */ @NoRepositoryBean -public interface R2dbcRepository extends ReactiveCrudRepository {} +public interface R2dbcRepository extends ReactiveSortingRepository {} diff --git a/src/main/java/org/springframework/data/r2dbc/repository/support/R2dbcRepositoryFactoryBean.java b/src/main/java/org/springframework/data/r2dbc/repository/support/R2dbcRepositoryFactoryBean.java index a16770ae..2c01b5a3 100644 --- a/src/main/java/org/springframework/data/r2dbc/repository/support/R2dbcRepositoryFactoryBean.java +++ b/src/main/java/org/springframework/data/r2dbc/repository/support/R2dbcRepositoryFactoryBean.java @@ -34,7 +34,7 @@ import org.springframework.util.Assert; * * @author Mark Paluch * @author Christoph Strobl - * @see org.springframework.data.repository.reactive.ReactiveCrudRepository + * @see org.springframework.data.repository.reactive.ReactiveSortingRepository */ public class R2dbcRepositoryFactoryBean, S, ID extends Serializable> extends RepositoryFactoryBeanSupport { diff --git a/src/main/java/org/springframework/data/r2dbc/repository/support/SimpleR2dbcRepository.java b/src/main/java/org/springframework/data/r2dbc/repository/support/SimpleR2dbcRepository.java index 2d96091f..8d677cd5 100644 --- a/src/main/java/org/springframework/data/r2dbc/repository/support/SimpleR2dbcRepository.java +++ b/src/main/java/org/springframework/data/r2dbc/repository/support/SimpleR2dbcRepository.java @@ -20,6 +20,7 @@ import reactor.core.publisher.Mono; import org.reactivestreams.Publisher; +import org.springframework.data.domain.Sort; import org.springframework.data.r2dbc.convert.R2dbcConverter; import org.springframework.data.r2dbc.core.DatabaseClient; import org.springframework.data.r2dbc.core.R2dbcEntityOperations; @@ -29,20 +30,21 @@ import org.springframework.data.relational.core.query.Criteria; import org.springframework.data.relational.core.mapping.RelationalPersistentProperty; import org.springframework.data.relational.core.query.Query; import org.springframework.data.relational.repository.query.RelationalEntityInformation; -import org.springframework.data.repository.reactive.ReactiveCrudRepository; +import org.springframework.data.repository.reactive.ReactiveSortingRepository; import org.springframework.data.util.Lazy; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.Assert; /** - * Simple {@link ReactiveCrudRepository} implementation using R2DBC through {@link DatabaseClient}. + * Simple {@link ReactiveSortingRepository} implementation using R2DBC through {@link DatabaseClient}. * * @author Mark Paluch * @author Jens Schauder * @author Mingyuan Wu + * @author Stephen Cohen */ @Transactional(readOnly = true) -public class SimpleR2dbcRepository implements ReactiveCrudRepository { +public class SimpleR2dbcRepository implements ReactiveSortingRepository { private final RelationalEntityInformation entity; private final R2dbcEntityOperations entityOperations; @@ -172,6 +174,14 @@ public class SimpleR2dbcRepository implements ReactiveCrudRepository findAll(Sort sort) { + return this.entityOperations.select(Query.empty().sort(sort), this.entity.getJavaType()); + } + /* (non-Javadoc) * @see org.springframework.data.repository.reactive.ReactiveCrudRepository#findAllById(java.lang.Iterable) */ diff --git a/src/test/java/org/springframework/data/r2dbc/repository/AbstractR2dbcRepositoryIntegrationTests.java b/src/test/java/org/springframework/data/r2dbc/repository/AbstractR2dbcRepositoryIntegrationTests.java index ba08de06..982847b6 100644 --- a/src/test/java/org/springframework/data/r2dbc/repository/AbstractR2dbcRepositoryIntegrationTests.java +++ b/src/test/java/org/springframework/data/r2dbc/repository/AbstractR2dbcRepositoryIntegrationTests.java @@ -48,7 +48,7 @@ import org.springframework.data.r2dbc.repository.support.R2dbcRepositoryFactory; import org.springframework.data.r2dbc.testing.R2dbcIntegrationTestSupport; import org.springframework.data.relational.core.mapping.Table; import org.springframework.data.repository.NoRepositoryBean; -import org.springframework.data.repository.reactive.ReactiveCrudRepository; +import org.springframework.data.repository.reactive.ReactiveSortingRepository; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.transaction.reactive.TransactionalOperator; @@ -56,6 +56,7 @@ import org.springframework.transaction.reactive.TransactionalOperator; * Abstract base class for integration tests for {@link LegoSetRepository} using {@link R2dbcRepositoryFactory}. * * @author Mark Paluch + * @author Stephen Cohen */ public abstract class AbstractR2dbcRepositoryIntegrationTests extends R2dbcIntegrationTestSupport { @@ -303,7 +304,7 @@ public abstract class AbstractR2dbcRepositoryIntegrationTests extends R2dbcInteg } @NoRepositoryBean - interface LegoSetRepository extends ReactiveCrudRepository { + interface LegoSetRepository extends ReactiveSortingRepository { Flux findByNameContains(String name); diff --git a/src/test/java/org/springframework/data/r2dbc/repository/support/AbstractSimpleR2dbcRepositoryIntegrationTests.java b/src/test/java/org/springframework/data/r2dbc/repository/support/AbstractSimpleR2dbcRepositoryIntegrationTests.java index cacbb18f..0c4329b4 100644 --- a/src/test/java/org/springframework/data/r2dbc/repository/support/AbstractSimpleR2dbcRepositoryIntegrationTests.java +++ b/src/test/java/org/springframework/data/r2dbc/repository/support/AbstractSimpleR2dbcRepositoryIntegrationTests.java @@ -39,6 +39,7 @@ import org.springframework.dao.OptimisticLockingFailureException; import org.springframework.data.annotation.Id; import org.springframework.data.annotation.Version; import org.springframework.data.domain.Persistable; +import org.springframework.data.domain.Sort; import org.springframework.data.r2dbc.convert.MappingR2dbcConverter; import org.springframework.data.r2dbc.core.DatabaseClient; import org.springframework.data.r2dbc.core.ReactiveDataAccessStrategy; @@ -55,6 +56,7 @@ import org.springframework.jdbc.core.JdbcTemplate; * * @author Mark Paluch * @author Bogdan Ilchyshyn + * @author Stephen Cohen */ public abstract class AbstractSimpleR2dbcRepositoryIntegrationTests extends R2dbcIntegrationTestSupport { @@ -313,6 +315,26 @@ public abstract class AbstractSimpleR2dbcRepositoryIntegrationTests extends R2db }).verifyComplete(); } + @Test // gh-407 + public void shouldFindAllWithSort() { + + jdbc.execute("INSERT INTO legoset (name, manual) VALUES('FORSCHUNGSSCHIFF', 13)"); + jdbc.execute("INSERT INTO legoset (name, manual) VALUES('SCHAUFELRADBAGGER', 12)"); + jdbc.execute("INSERT INTO legoset (name, manual) VALUES('VOLTRON', 15)"); + jdbc.execute("INSERT INTO legoset (name, manual) VALUES('RALLYEAUTO', 14)"); + + repository.findAll(Sort.by("manual").ascending()) // + .map(LegoSet::getName) // + .collectList() // + .as(StepVerifier::create) // + .assertNext(actual -> assertThat(actual).containsExactly( + "SCHAUFELRADBAGGER", + "FORSCHUNGSSCHIFF", + "RALLYEAUTO", + "VOLTRON" + )).verifyComplete(); + } + @Test public void shouldFindAllByIdUsingIterable() {