jpa-spec github: https://github.com/wenhao/jpa-spec
Using this framework can simplify the complexity of our fight conditions, the following code:
public Page<Person> findAll(SearchRequest request) { Specification<Person> specification = Specifications.<Person>and() .eq(StringUtils.isNotBlank(request.getName()), "name", request.getName()) .gt("age", 18) .between("birthday", new Date(), new Date()) .like("nickName", "%og%") .build(); Sort sort = Sorts.builder() .desc(StringUtils.isNotBlank(request.getName()), "name" .Asc ()"birthday") .build(); return personRepository.findAll(specification, new PageRequest(0, 15, sort)); }
This is a page + sorted query.
But if we are using a database-specific functions, methods provided by this framework is not good enough, we need to expand:
We are using oracle database, it functions as bitand, instr we need to expand:
jpa-spec bitand extension:
/** * Oracle bitand函数 计算扣款规则rulebit * * @author :hkk * @date :Created in 2019/7/24 10:34 */ public class BitandSpecification<T> extends AbstractSpecification<T> { private String property; private List<BigDecimal> values; public BitandSpecification(String property, List<BigDecimal> values) { this.property = property; this.values = values; } @Override public Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder cb) { BigDecimal sum = values.stream().reduce(BigDecimal::add).get(); LiteralExpression<BigDecimal> literalExpression = new LiteralExpression<>(null, sum); Expression<BigDecimal> ruleBit = cb.function("bitand", BigDecimal.class, root.get(property), literalExpression); return cb.greaterThan(ruleBit, BigDecimal.ZERO); } }
jpa-spec instr extension:
/** * Oracle instr函数 计算扣款规则rulebit * * @author :hkk * @date :Created in 2019/7/24 10:34 */ public class IntstrSpecification<T> extends AbstractSpecification<T> { private String property; private String value; public IntstrSpecification(String property, String value) { this.property = property; this.value = value; } @Override public Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder cb) { LiteralExpression literalExpression = new LiteralExpression(null, value); Expression<BigDecimal> instr = cb.function("instr", BigDecimal.class, root.get(property), literalExpression); return cb.greaterThan(instr, BigDecimal.ZERO); } }
We then modify PredicateBuilder class: the addition of two methods:
/** * oracle 函数bitand * @param property * @param var * @return */ public PredicateBuilder<T> bitand(String property, List var) { if (!CollectionUtils.isEmpty(var)) { this.predicate(true, new BitandSpecification(property, var)); } return this; } /** * oracle 函数instr * @param property * @param var * @return */ public PredicateBuilder<T> instr(String property, String var) { if (StringUtils.isNotBlank(var)) { this.predicate(true, new IntstrSpecification(property, var)); } return this; }
We added some method, passing judgment parameter is null, reducing the amount of code developers:
/ ** * value is not empty in * @param Property * @param values * @return * / public PredicateBuilder <T> inWhereHasValues (String Property, List values) { IF (! CollectionUtils.isEmpty (values)) { the this . in (Property, values); } return the this ; } / ** * when the null values is empty iS * is not empty when the values in * @param Property * @param values * @return * / public PredicateBuilder<T> inAndNull(String property, List values) { if (CollectionUtils.isEmpty(values)) { return this.eq(property, values); } return in(property,values); } public PredicateBuilder<T> eqWhereHasValue(String property, Object... values) { if (values == null) { return this; } if (values.length == 1) { if (values[0] == null) { return this; } if (StringUtils.isBlank(String.valueOf(values[0]))) { return this; } } return eq(true, property, values); }
We want to help students jps just getting started, we can be considered back to the community :)