Skip to content

Commit 0b07c44

Browse files
committed
Implement Query by Example.
Implement Spring Data's Query by Example feature. See #532 and spring-projects/spring-data-relational#929.
1 parent 0841e1a commit 0b07c44

File tree

9 files changed

+396
-26
lines changed

9 files changed

+396
-26
lines changed

Diff for: pom.xml

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
2-
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
2+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
34

45
<modelVersion>4.0.0</modelVersion>
56

Diff for: src/main/java/org/springframework/data/r2dbc/repository/R2dbcRepository.java

+3-1
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,15 @@
1616
package org.springframework.data.r2dbc.repository;
1717

1818
import org.springframework.data.repository.NoRepositoryBean;
19+
import org.springframework.data.repository.query.ReactiveQueryByExampleExecutor;
1920
import org.springframework.data.repository.reactive.ReactiveSortingRepository;
2021

2122
/**
2223
* R2DBC specific {@link org.springframework.data.repository.Repository} interface with reactive support.
2324
*
2425
* @author Mark Paluch
2526
* @author Stephen Cohen
27+
* @author Greg Turnquist
2628
*/
2729
@NoRepositoryBean
28-
public interface R2dbcRepository<T, ID> extends ReactiveSortingRepository<T, ID> {}
30+
public interface R2dbcRepository<T, ID> extends ReactiveSortingRepository<T, ID>, ReactiveQueryByExampleExecutor<T> {}

Diff for: src/main/java/org/springframework/data/r2dbc/repository/support/SimpleR2dbcRepository.java

+62-2
Original file line numberDiff line numberDiff line change
@@ -21,16 +21,18 @@
2121
import java.util.List;
2222

2323
import org.reactivestreams.Publisher;
24-
24+
import org.springframework.data.domain.Example;
2525
import org.springframework.data.domain.Sort;
2626
import org.springframework.data.r2dbc.convert.R2dbcConverter;
2727
import org.springframework.data.r2dbc.core.R2dbcEntityOperations;
2828
import org.springframework.data.r2dbc.core.R2dbcEntityTemplate;
2929
import org.springframework.data.r2dbc.core.ReactiveDataAccessStrategy;
30+
import org.springframework.data.r2dbc.repository.R2dbcRepository;
3031
import org.springframework.data.relational.core.mapping.RelationalPersistentProperty;
3132
import org.springframework.data.relational.core.query.Criteria;
3233
import org.springframework.data.relational.core.query.Query;
3334
import org.springframework.data.relational.repository.query.RelationalEntityInformation;
35+
import org.springframework.data.relational.repository.query.RelationalExampleMapper;
3436
import org.springframework.data.repository.reactive.ReactiveSortingRepository;
3537
import org.springframework.data.util.Lazy;
3638
import org.springframework.data.util.Streamable;
@@ -45,13 +47,15 @@
4547
* @author Jens Schauder
4648
* @author Mingyuan Wu
4749
* @author Stephen Cohen
50+
* @author Greg Turnquist
4851
*/
4952
@Transactional(readOnly = true)
50-
public class SimpleR2dbcRepository<T, ID> implements ReactiveSortingRepository<T, ID> {
53+
public class SimpleR2dbcRepository<T, ID> implements R2dbcRepository<T, ID> {
5154

5255
private final RelationalEntityInformation<T, ID> entity;
5356
private final R2dbcEntityOperations entityOperations;
5457
private final Lazy<RelationalPersistentProperty> idProperty;
58+
private final RelationalExampleMapper exampleMapper;
5559

5660
/**
5761
* Create a new {@link SimpleR2dbcRepository}.
@@ -70,6 +74,7 @@ public SimpleR2dbcRepository(RelationalEntityInformation<T, ID> entity, R2dbcEnt
7074
.getMappingContext() //
7175
.getRequiredPersistentEntity(this.entity.getJavaType()) //
7276
.getRequiredIdProperty());
77+
this.exampleMapper = new RelationalExampleMapper(converter.getMappingContext());
7378
}
7479

7580
/**
@@ -90,6 +95,7 @@ public SimpleR2dbcRepository(RelationalEntityInformation<T, ID> entity, Database
9095
.getMappingContext() //
9196
.getRequiredPersistentEntity(this.entity.getJavaType()) //
9297
.getRequiredIdProperty());
98+
this.exampleMapper = new RelationalExampleMapper(converter.getMappingContext());
9399
}
94100

95101
/**
@@ -112,6 +118,7 @@ public SimpleR2dbcRepository(RelationalEntityInformation<T, ID> entity,
112118
.getMappingContext() //
113119
.getRequiredPersistentEntity(this.entity.getJavaType()) //
114120
.getRequiredIdProperty());
121+
this.exampleMapper = new RelationalExampleMapper(converter.getMappingContext());
115122
}
116123

117124
// -------------------------------------------------------------------------
@@ -372,6 +379,59 @@ public Flux<T> findAll(Sort sort) {
372379
return this.entityOperations.select(Query.empty().sort(sort), this.entity.getJavaType());
373380
}
374381

382+
// -------------------------------------------------------------------------
383+
// Methods from ReactiveQueryByExampleExecutor
384+
// -------------------------------------------------------------------------
385+
386+
@Override
387+
public <S extends T> Mono<S> findOne(Example<S> example) {
388+
389+
Assert.notNull(example, "Example must not be null!");
390+
391+
Query query = this.exampleMapper.getMappedExample(example);
392+
393+
return this.entityOperations.selectOne(query, example.getProbeType());
394+
}
395+
396+
@Override
397+
public <S extends T> Flux<S> findAll(Example<S> example) {
398+
399+
Assert.notNull(example, "Example must not be null!");
400+
401+
return findAll(example, Sort.unsorted());
402+
}
403+
404+
@Override
405+
public <S extends T> Flux<S> findAll(Example<S> example, Sort sort) {
406+
407+
Assert.notNull(example, "Example must not be null!");
408+
Assert.notNull(sort, "Sort must not be null!");
409+
410+
Query query = this.exampleMapper.getMappedExample(example).sort(sort);
411+
412+
return this.entityOperations.select(query, example.getProbeType());
413+
}
414+
415+
@Override
416+
public <S extends T> Mono<Long> count(Example<S> example) {
417+
418+
Assert.notNull(example, "Example must not be null!");
419+
420+
Query query = this.exampleMapper.getMappedExample(example);
421+
422+
return this.entityOperations.count(query, example.getProbeType());
423+
}
424+
425+
@Override
426+
public <S extends T> Mono<Boolean> exists(Example<S> example) {
427+
428+
Assert.notNull(example, "Example must not be null!");
429+
430+
Query query = this.exampleMapper.getMappedExample(example);
431+
432+
return this.entityOperations.exists(query, example.getProbeType());
433+
}
434+
375435
private RelationalPersistentProperty getIdProperty() {
376436
return this.idProperty.get();
377437
}

Diff for: src/test/java/org/springframework/data/r2dbc/repository/ConvertingR2dbcRepositoryIntegrationTests.java

-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@
3232
import org.junit.jupiter.api.BeforeEach;
3333
import org.junit.jupiter.api.Test;
3434
import org.junit.jupiter.api.extension.ExtendWith;
35-
3635
import org.springframework.beans.factory.annotation.Autowired;
3736
import org.springframework.context.annotation.ComponentScan;
3837
import org.springframework.context.annotation.Configuration;

0 commit comments

Comments
 (0)