Spring Data JPA实现动态条件与范围查询实例代码
程序员文章站
2023-12-16 19:28:46
spring data jpa为我们提供了query with example来实现动态条件查询,当查询条件为空的时候,我们不用做大量的条件判断。但是query with...
spring data jpa
为我们提供了query with example
来实现动态条件查询,当查询条件为空的时候,我们不用做大量的条件判断。但是query with example
却不支持范围查询(包括日期范围,数值范围查询),本文通过specification
实现了既支持动态条件查询又支持范围查询的方法。
1 实现方式
1.1 范围对象range定义
import java.io.serializable; public class range<e> implements serializable { private static final long serialversionuid = 1l; private string field; private comparable from; private comparable to; private boolean includenull; public range(string field) { this.field = field; } public range(string field, comparable from, comparable to) { this.field = field; this.from = from; this.to = to; } public range(string field, comparable from, comparable to, boolean includenull) { this.field = field; this.from = from; this.to = to; this.includenull = includenull; } public range(range<e> other) { this.field = other.getfield(); this.from = other.getfrom(); this.to = other.getto(); this.includenull = other.getincludenull(); } public string getfield() { return field; } public comparable getfrom() { return from; } public void setfrom(comparable from) { this.from = from; } public boolean isfromset() { return getfrom() != null; } public comparable getto() { return to; } public void setto(comparable to) { this.to = to; } public boolean istoset() { return getto() != null; } public void setincludenull(boolean includenull) { this.includenull = includenull; } public boolean getincludenull() { return includenull; } public boolean isincludenullset() { return includenull != null; } public boolean isbetween() { return isfromset() && istoset(); } public boolean isset() { return isfromset() || istoset() || isincludenullset(); } public boolean isvalid() { if (isbetween()) { return getfrom().compareto(getto()) <= 0; } return true; } }
1.2 example的specification
import org.springframework.data.domain.example; import org.springframework.data.jpa.convert.querybyexamplepredicatebuilder; 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; /** * created by wangyunfei on 2017/6/6. */ public class byexamplespecification<t> implements specification<t> { private final example<t> example; public byexamplespecification(example<t> example) { assert.notnull(example, "example must not be null!"); this.example = example; } @override public predicate topredicate(root<t> root, criteriaquery<?> query, criteriabuilder cb) { return querybyexamplepredicatebuilder.getpredicate(root, cb, example); } }
1.3 range的specification
import org.springframework.data.jpa.domain.specification; import javax.persistence.criteria.criteriabuilder; import javax.persistence.criteria.criteriaquery; import javax.persistence.criteria.predicate; import javax.persistence.criteria.root; import java.util.list; import static com.google.common.collect.iterables.toarray; import static com.google.common.collect.lists.newarraylist; import static java.lang.boolean.false; import static java.lang.boolean.true; /** * created by wangyunfei on 2017/6/6. */ public class byrangespecification<t> implements specification<t> { private final list<range<t>> ranges; public byrangespecification(list<range<t>> ranges) { this.ranges = ranges; } @override public predicate topredicate(root<t> root, criteriaquery<?> query, criteriabuilder builder) { list<predicate> predicates = newarraylist(); for (range<t> range : ranges) { if (range.isset()) { predicate rangepredicate = buildrangepredicate(range, root, builder); if (rangepredicate != null) { if (!range.isincludenullset() || range.getincludenull() == false) { predicates.add(rangepredicate); } else { predicates.add(builder.or(rangepredicate, builder.isnull(root.get(range.getfield())))); } } if (true == range.getincludenull()) { predicates.add(builder.isnull(root.get(range.getfield()))); } else if (false == range.getincludenull()) { predicates.add(builder.isnotnull(root.get(range.getfield()))); } } } return predicates.isempty() ? builder.conjunction() : builder.and(toarray(predicates, predicate.class)); } private predicate buildrangepredicate(range<t> range, root<t> root, criteriabuilder builder) { if (range.isbetween()) { return builder.between(root.get(range.getfield()), range.getfrom(), range.getto()); } else if (range.isfromset()) { return builder.greaterthanorequalto(root.get(range.getfield()), range.getfrom()); } else if (range.istoset()) { return builder.lessthanorequalto(root.get(range.getfield()), range.getto()); } return null; } }
1.4 自定义repository与实现
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.io.serializable; import java.util.list; @norepositorybean public interface wiselyrepository<e, pk extends serializable> extends jparepository<e, pk> { page<e> querybyexamplewithrange(example example,list<range<e>> ranges, pageable pageable); }
import org.springframework.data.domain.example; import org.springframework.data.domain.page; import org.springframework.data.domain.pageable; import org.springframework.data.jpa.domain.specification; import org.springframework.data.jpa.repository.support.jpaentityinformation; import org.springframework.data.jpa.repository.support.simplejparepository; import javax.persistence.entitymanager; import java.io.serializable; import java.util.list; import static org.springframework.data.jpa.domain.specifications.where; public class wiselyrepositoryimpl<e, pk extends serializable> extends simplejparepository<e, pk> implements wiselyrepository<e, pk> { private final entitymanager entitymanager; public wiselyrepositoryimpl(jpaentityinformation entityinformation, entitymanager entitymanager) { super(entityinformation, entitymanager); this.entitymanager = entitymanager; } @override public page<e> querybyexamplewithrange(example example, list<range<e>> ranges, pageable pageable) { specification<e> byexample = new byexamplespecification<>(example); specification<e> byranges = new byrangespecification<>(ranges); return findall(where(byexample).and(byranges),pageable); } }
2 使用方式
2.1 开启支持
通过@enablejparepositories(repositorybaseclass = wiselyrepositoryimpl.class)
开启对定义功能的支持。
2.2 示例
实体类
@entity @data @allargsconstructor @noargsconstructor public class person { @id @generatedvalue private long id; private string name; private integer height; @datetimeformat(pattern = "yyyy-mm-dd") private date birthday; }
personrepository
public interface personrepository extends wiselyrepository<person,long> { }
测试控制器
@restcontroller @requestmapping("/people") public class personcontroller { @autowired personrepository personrepository; @postmapping public responseentity<person> save(@requestbody person person){ person p = personrepository.save(person); return new responseentity<person>(p, httpstatus.created); } @getmapping public responseentity<page<person>> query(person person, @datetimeformat(pattern = "yyyy-mm-dd")date startdate, @datetimeformat(pattern = "yyyy-mm-dd")date enddate, integer startheight, integer endheight, pageable pageable){ example<person> personexample = example.of(person); list<range<person>> ranges = newarraylist(); range<person> birthrange = new range<person>("birthday",startdate,enddate); range<person> heightrange = new range<person>("height",startheight,endheight); ranges.add(birthrange); ranges.add(heightrange); page<person> page = personrepository.querybyexamplewithrange(personexample,ranges,pageable); return new responseentity<page<person>>(page,httpstatus.ok); } }
源码地址:
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。