diff --git a/pom.xml b/pom.xml index eea61f492c..e5b873f787 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ org.springframework.data spring-data-mongodb-parent - 2.0.0.BUILD-SNAPSHOT + 2.0.0.DATAMONGO-1619-SNAPSHOT pom Spring Data MongoDB @@ -28,9 +28,9 @@ multi spring-data-mongodb - 2.0.0.BUILD-SNAPSHOT - 3.4.2 - 1.3.0 + 2.0.0.DATACMNS-995-SNAPSHOT + 3.4.2 + 1.3.0 diff --git a/spring-data-mongodb-cross-store/pom.xml b/spring-data-mongodb-cross-store/pom.xml index 4a49168713..875b42d97f 100644 --- a/spring-data-mongodb-cross-store/pom.xml +++ b/spring-data-mongodb-cross-store/pom.xml @@ -6,7 +6,7 @@ org.springframework.data spring-data-mongodb-parent - 2.0.0.BUILD-SNAPSHOT + 2.0.0.DATAMONGO-1619-SNAPSHOT ../pom.xml @@ -48,7 +48,7 @@ org.springframework.data spring-data-mongodb - 2.0.0.BUILD-SNAPSHOT + 2.0.0.DATAMONGO-1619-SNAPSHOT diff --git a/spring-data-mongodb-distribution/pom.xml b/spring-data-mongodb-distribution/pom.xml index 750ed23aa8..5642ca4eaa 100644 --- a/spring-data-mongodb-distribution/pom.xml +++ b/spring-data-mongodb-distribution/pom.xml @@ -13,7 +13,7 @@ org.springframework.data spring-data-mongodb-parent - 2.0.0.BUILD-SNAPSHOT + 2.0.0.DATAMONGO-1619-SNAPSHOT ../pom.xml diff --git a/spring-data-mongodb-log4j/pom.xml b/spring-data-mongodb-log4j/pom.xml index 50d0a6454a..477d39a208 100644 --- a/spring-data-mongodb-log4j/pom.xml +++ b/spring-data-mongodb-log4j/pom.xml @@ -5,7 +5,7 @@ org.springframework.data spring-data-mongodb-parent - 2.0.0.BUILD-SNAPSHOT + 2.0.0.DATAMONGO-1619-SNAPSHOT ../pom.xml diff --git a/spring-data-mongodb/pom.xml b/spring-data-mongodb/pom.xml index 886bcca7b6..3bf1e6af24 100644 --- a/spring-data-mongodb/pom.xml +++ b/spring-data-mongodb/pom.xml @@ -11,7 +11,7 @@ org.springframework.data spring-data-mongodb-parent - 2.0.0.BUILD-SNAPSHOT + 2.0.0.DATAMONGO-1619-SNAPSHOT ../pom.xml diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/ReactiveMongoRepository.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/ReactiveMongoRepository.java index 0dd08c263e..edb622b3c8 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/ReactiveMongoRepository.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/ReactiveMongoRepository.java @@ -22,6 +22,7 @@ import org.springframework.data.domain.Example; import org.springframework.data.domain.Sort; import org.springframework.data.repository.NoRepositoryBean; +import org.springframework.data.repository.query.ReactiveQueryByExampleExecutor; import org.springframework.data.repository.reactive.ReactiveSortingRepository; /** @@ -31,7 +32,7 @@ * @since 2.0 */ @NoRepositoryBean -public interface ReactiveMongoRepository extends ReactiveSortingRepository { +public interface ReactiveMongoRepository extends ReactiveSortingRepository, ReactiveQueryByExampleExecutor { /** * Inserts the given entity. Assumes the instance to be new to be able to apply insertion optimizations. Use the diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SimpleReactiveMongoRepository.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SimpleReactiveMongoRepository.java index b6f1e8678c..9560f9e6ab 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SimpleReactiveMongoRepository.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/support/SimpleReactiveMongoRepository.java @@ -27,6 +27,7 @@ import java.util.stream.Collectors; import org.reactivestreams.Publisher; +import org.springframework.dao.IncorrectResultSizeDataAccessException; import org.springframework.data.domain.Example; import org.springframework.data.domain.Sort; import org.springframework.data.mongodb.core.ReactiveMongoOperations; @@ -43,6 +44,7 @@ * * @author Mark Paluch * @author Oliver Gierke + * @author Christoph Strobl * @since 2.0 */ @RequiredArgsConstructor @@ -76,6 +78,28 @@ public Mono findById(Mono mono) { id -> mongoOperations.findById(id, entityInformation.getJavaType(), entityInformation.getCollectionName())); } + /* + * (non-Javadoc) + * @see org.springframework.data.repository.query.ReactiveQueryByExampleExecutor#findOne(org.springframework.data.domain.Example) + */ + @Override + public Mono findOne(Example example) { + + Assert.notNull(example, "Sample must not be null!"); + + Query q = new Query(new Criteria().alike(example)); + q.limit(2); + + return mongoOperations.find(q, example.getProbeType(), entityInformation.getCollectionName()).buffer(2) + .flatMap(vals -> { + + if (vals.size() > 1) { + return Mono.error(new IncorrectResultSizeDataAccessException(1)); + } + return Mono.just(vals.iterator().next()); + }).single(); + } + /* * (non-Javadoc) * @see org.springframework.data.repository.reactive.ReactiveCrudRepository#existsById(java.lang.Object) @@ -103,6 +127,23 @@ public Mono existsById(Mono mono) { } + /* + * (non-Javadoc) + * @see org.springframework.data.repository.query.ReactiveQueryByExampleExecutor#exists(org.springframework.data.domain.Example) + */ + @Override + public Mono exists(Example example) { + + Assert.notNull(example, "Sample must not be null!"); + + Query q = new Query(new Criteria().alike(example)); + return mongoOperations.exists(q, example.getProbeType(), entityInformation.getCollectionName()); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.repository.reactive.ReactiveSortingRepository#findAll() + */ @Override public Flux findAll() { return findAll(new Query()); @@ -170,10 +211,24 @@ public Flux findAll(Example example) { * (non-Javadoc) * @see org.springframework.data.repository.reactive.ReactiveCrudRepository#count() */ + @Override public Mono count() { return mongoOperations.count(new Query(), entityInformation.getCollectionName()); } + /* + * (non-Javadoc) + * @see org.springframework.data.repository.query.ReactiveQueryByExampleExecutor#count(org.springframework.data.domain.Example) + */ + @Override + public Mono count(Example example) { + + Assert.notNull(example, "Sample must not be null!"); + + Query q = new Query(new Criteria().alike(example)); + return mongoOperations.count(q, example.getProbeType(), entityInformation.getCollectionName()); + } + /* * (non-Javadoc) * @see org.springframework.data.mongodb.repository.ReactiveMongoRepository#insert(java.lang.Object) @@ -315,34 +370,11 @@ public Mono deleteAll(Publisher entityStream) { * (non-Javadoc) * @see org.springframework.data.repository.reactive.ReactiveCrudRepository#deleteAll() */ + @Override public Mono deleteAll() { return mongoOperations.remove(new Query(), entityInformation.getCollectionName()).then(Mono.empty()); } - public Mono exists(Example example) { - - Assert.notNull(example, "Sample must not be null!"); - - Query q = new Query(new Criteria().alike(example)); - return mongoOperations.exists(q, example.getProbeType(), entityInformation.getCollectionName()); - } - - public Mono findOne(Example example) { - - Assert.notNull(example, "Sample must not be null!"); - - Query q = new Query(new Criteria().alike(example)); - return mongoOperations.findOne(q, example.getProbeType(), entityInformation.getCollectionName()); - } - - public Mono count(Example example) { - - Assert.notNull(example, "Sample must not be null!"); - - Query q = new Query(new Criteria().alike(example)); - return mongoOperations.count(q, example.getProbeType(), entityInformation.getCollectionName()); - } - private Query getIdQuery(Object id) { return new Query(getIdCriteria(id)); } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/SimpleReactiveMongoRepositoryTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/SimpleReactiveMongoRepositoryTests.java index e45044f1b2..660548a03e 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/SimpleReactiveMongoRepositoryTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/SimpleReactiveMongoRepositoryTests.java @@ -17,6 +17,7 @@ import static org.hamcrest.Matchers.*; import static org.junit.Assert.*; +import static org.springframework.data.domain.ExampleMatcher.*; import lombok.Data; import lombok.NoArgsConstructor; @@ -34,7 +35,9 @@ import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.BeanFactoryAware; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.IncorrectResultSizeDataAccessException; import org.springframework.data.annotation.Id; +import org.springframework.data.domain.Example; import org.springframework.data.domain.Sort; import org.springframework.data.domain.Sort.Direction; import org.springframework.data.domain.Sort.Order; @@ -47,9 +50,10 @@ import org.springframework.util.ClassUtils; /** - * Test for {@link ReactiveMongoRepository}. + * Tests for {@link ReactiveMongoRepository}. * * @author Mark Paluch + * @author Christoph Strobl */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("classpath:reactive-infrastructure.xml") @@ -353,6 +357,63 @@ public void deletePublisherOfEntitiesShouldRemoveEntities() { StepVerifier.create(repository.findByLastname("Matthews")).expectNext(oliver).verifyComplete(); } + @Test // DATAMONGO-1619 + public void findOneByExampleShouldReturnObject() { + + Example example = Example.of(dave); + + StepVerifier.create(repository.findOne(example)).expectNext(dave).verifyComplete(); + } + + @Test // DATAMONGO-1619 + public void findAllByExampleShouldReturnObjects() { + + Example example = Example.of(dave, matching().withIgnorePaths("id", "age", "firstname")); + + StepVerifier.create(repository.findAll(example)).expectNextCount(2).verifyComplete(); + } + + @Test // DATAMONGO-1619 + public void findAllByExampleAndSortShouldReturnObjects() { + + Example example = Example.of(dave, matching().withIgnorePaths("id", "age", "firstname")); + + StepVerifier.create(repository.findAll(example, Sort.by("firstname"))).expectNext(dave, oliver).verifyComplete(); + } + + @Test // DATAMONGO-1619 + public void countByExampleShouldCountObjects() { + + Example example = Example.of(dave, matching().withIgnorePaths("id", "age", "firstname")); + + StepVerifier.create(repository.count(example)).expectNext(2L).verifyComplete(); + } + + @Test // DATAMONGO-1619 + public void existsByExampleShouldReturnExisting() { + + Example example = Example.of(dave, matching().withIgnorePaths("id", "age", "firstname")); + + StepVerifier.create(repository.exists(example)).expectNext(true).verifyComplete(); + } + + @Test // DATAMONGO-1619 + public void existsByExampleShouldReturnNonExisting() { + + Example example = Example.of(new ReactivePerson("foo", "bar", -1)); + + StepVerifier.create(repository.exists(example)).expectNext(false).verifyComplete(); + } + + @Test // DATAMONGO-1619 + public void findOneShouldEmitIncorrectResultSizeDataAccessExceptionWhenMoreThanOneElementFound() { + + Example example = Example.of(new ReactivePerson(null, "Matthews", -1), + matching().withIgnorePaths("age")); + + StepVerifier.create(repository.findOne(example)).expectError(IncorrectResultSizeDataAccessException.class); + } + interface ReactivePersonRepostitory extends ReactiveMongoRepository { Flux findByLastname(String lastname);