Extending Spring Data QBE to realize dynamic range query
Spring Data JPA provides Query by Example (QBE) query technology to realize dynamic condition query without having to write tedious condition judgment. But QBE does not support range query. In this paper, dynamic range query is implemented by combining QBE and Specification.
This paper modifies the example code of dynamic condition and range query implemented by Wang Yunfei-Spring Data JPA, replaces the custom implementation with org.springframework.data.domain.Range, supports Matching Any, and maintains the basic structure of the original code. Source code address https://github.com/sunjc/heroes-api
Implementation code FieldRangeimport org.springframework.data.domain.Range;import org.springframework.data.domain.Range.Bound;import static org.springframework.data.domain.Range.Bound.inclusive;public class FieldRange {private String field; private Range range; public FieldRange (String field, T lower, T upper) {this.field = field; this.range = of (lower, upper);} private Range of (T lower, T upper) {Bound lowerBound = Bound.unbounded () Bound upperBound = Bound.unbounded (); if (lower! = null) {lowerBound = inclusive (lower);} if (upper! = null) {upperBound = inclusive (upper);} return Range.of (lowerBound, upperBound);} public String getField () {return field;} public Range getRange () {return range;} ExampleSpecification
The Specification,SimpleJpaRepository that extracts the Example contains this class and is private.
Import org.springframework.data.domain.Example;import org.springframework.data.jpa.domain.Specification;import org.springframework.util.Assert;import javax.persistence.criteria.CriteriaBuilder;import javax.persistence.criteria.CriteriaQuery;import javax.persistence.criteria.Predicate;import javax.persistence.criteria.Root;import static org.springframework.data.jpa.convert.QueryByExamplePredicateBuilder.getPredicate;public class ExampleSpecification implements Specification {private static final long serialVersionUID = 1L; private final Example example / / NOSONAR public ExampleSpecification (Example example) {Assert.notNull (example, "Example must not be null!"); this.example = example;} @ Override public Predicate toPredicate (Root root, CriteriaQuery query, CriteriaBuilder criteriaBuilder) {return getPredicate (root, criteriaBuilder, example);} RangeSpecificationimport org.springframework.data.jpa.domain.Specification;import javax.persistence.criteria.*;import java.util.Optional;public class RangeSpecification implements Specification {private FieldRange fieldRange / / NOSONAR public RangeSpecification (FieldRange fieldRange) {this.fieldRange = fieldRange;} @ Override public Predicate toPredicate (Root root, CriteriaQuery query, CriteriaBuilder builder) {Optional lower = fieldRange.getRange (). GetLowerBound (). GetValue (); Optional upper = fieldRange.getRange (). GetUpperBound (). GetValue (); Path path = root.get (fieldRange.getField ()) If (lower.isPresent () & & upper.isPresent ()) {return builder.between (path, lower.get (), upper.get ());} if (lower.isPresent ()) {return builder.greaterThanOrEqualTo (path, lower.get ());} if (upper.isPresent ()) {return builder.lessThanOrEqualTo (path, upper.get ()) } return null;}} Custom Repository
WiselyRepository interface
Import org.itrunner.heroes.repository.specifications.FieldRange;import org.springframework.data.domain.Example;import org.springframework.data.domain.Page;import org.springframework.data.domain.Pageable;import org.springframework.data.jpa.repository.JpaRepository;import org.springframework.data.repository.NoRepositoryBean;import java.util.List;@NoRepositoryBeanpublic interface WiselyRepository extends JpaRepository {/ / NOSONAR Page findByExampleAndRange (Example example, List entityInformation, EntityManager entityManager) {super (entityInformation, entityManager);} @ Override public Page findByExampleAndRange (Example example, List