分页查询、分页排序查询、普通条件查询、多表连接条件查询;查询条件类型包括枚举、日期以及java基础类型
spring data jpa:2.1.1.RELEASE
jpa-spec:3.2.3
google guava:27.0.1-jre
jdk:1.8
import com.github.wenhao.jpa.PredicateBuilder;
import com.github.wenhao.jpa.Specifications;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.xxxx.xxx.common.enums.Behavior;
import com.xxxx.xxx.common.enums.DateFormat;
import com.xxxx.xxx.common.util.ReflectionUtils;
import lombok.Data;
import org.apache.commons.lang3.time.DateUtils;
import org.springframework.data.domain.*;
import org.springframework.data.jpa.domain.Specification;
import javax.persistence.criteria.Predicate;
import java.text.ParseException;
import java.util.*;
import java.util.stream.Collectors;
/**
* 作者: 673164808@qq.com
* 功能:spring data jpa查询(包括分页,基于jpa-spec扩展)
*/
@Data
public class PageEntity {
/**页码*/
private Integer page;
/**展示数据数量*/
private Integer size;
/**要条件查询对象的class*/
private Class clazz;
/**查询排序*/
private Set<Order> orders;
/**条件查询参数*/
private List<specificationParam> params;
/**
* 分页及排序
*/
public Pageable getPageable(){
return PageRequest.of(page,size,this.getSorts(orders));
}
/**
* 排序,内部调用
* @param orders
* @return
*/
private Sort getSorts(Set<Order> orders){
List<Sort.Order> orderList = orders.stream().map(order -> new Sort.Order(order.sort,order.name)).collect(Collectors.toList());
return Sort.by(orderList);
}
/**
* 排序
* @return
*/
public Sort getSort(){
List<Sort.Order> orderList = orders.stream().map(order -> new Sort.Order(order.sort,order.name)).collect(Collectors.toList());
return Sort.by(orderList);
}
/**
* 获取查询条件
* @param clazz
* @return
*/
public Specification getSpecification(Class clazz) {
this.clazz = clazz;
Specification result = null;
for (specificationParam sp:params) {
if (Predicate.BooleanOperator.AND.equals(sp.getCt())){
if(Objects.isNull(result)){
result = builderBehavior(Specifications.and(),sp).build();
}else{
result = result.and(builderBehavior(Specifications.and(),sp).build());
}
}else{
if(Objects.isNull(result)){
result = builderBehavior(Specifications.or(),sp).build();
}else{
result = result.or(builderBehavior(Specifications.or(),sp).build());
}
}
}
return result;
}
/**
* 匹配查询条件行为
* @param predicateBuilder
* @param sp
* @return
*/
private PredicateBuilder builderBehavior(PredicateBuilder predicateBuilder,specificationParam sp) {
PredicateBuilder result = null;
sp.setParams(parseParams(sp.getName(),sp.getParams()));
switch (sp.getBehavior()){
case BW: result = predicateBuilder.between(sp.getName(),sp.getParams().get(0),sp.getParams().get(1));break;
case EQ: result = predicateBuilder.eq(sp.getName(),sp.getParams().stream().toArray());break;
case GE: result = predicateBuilder.ge(sp.getName(),(Comparable)sp.getParams().stream().findFirst().get());break;
case GT: result = predicateBuilder.gt(sp.getName(),(Comparable)sp.getParams().stream().findFirst().get());break;
case IN: result = predicateBuilder.in(sp.getName(),sp.getParams().stream().toArray());break;
case LE: result = predicateBuilder.le(sp.getName(),(Comparable)sp.getParams().stream().findFirst().get());break;
case LK: result = predicateBuilder.like(sp.getName(), sp.getParams().stream().toArray(String[]::new));break;
case LT: result = predicateBuilder.lt(sp.getName(),(Comparable)sp.getParams().stream().findFirst().get());break;
case NE: result = predicateBuilder.ne(sp.getName(),sp.getParams().stream().toArray());break;
case NI: result = predicateBuilder.notIn(sp.getName(),sp.getParams().stream().toArray());break;
case NL: result = predicateBuilder.notLike(sp.getName(), sp.getParams().stream().toArray(String[]::new));break;
}
return result;
}
/**
* 查询条件解析
* @param name
* @param params
* @return
*/
private List<Object> parseParams(String name,List<Object> params) {
clazz = ReflectionUtils.getFieldClass(clazz, name);
List<Object> resultParams = Lists.newArrayListWithCapacity(2);
if(clazz.isEnum()){
for (Object param:params) {
resultParams.add(Enum.valueOf(clazz, param.toString()));
}
}else if(clazz.equals(Date.class)){
try {
for (Object param:params) {
String[] dateFormats = Lists.newArrayList(DateFormat.values()).stream().map(dateFormat -> dateFormat.getDateFormat()).collect(Collectors.toList()).stream().toArray(String[]::new);
resultParams.add(DateUtils.parseDate(param.toString(),dateFormats));
}
} catch (ParseException e) {
e.printStackTrace();
}
}
return Iterables.isEmpty(resultParams)?params:resultParams;
}
/**
* 查询条件内部类
*/
@Data
static class specificationParam{
/**查询条件之间的关系(and/or)*/
private Predicate.BooleanOperator ct = Predicate.BooleanOperator.AND;
/**查询条件的行为(等于、大于、小于……)*/
private Behavior behavior;
/**查询条件的参数集合*/
private List<Object> params;
/**查询条件的name*/
private String name;
}
/**
* 排序内部类,过滤掉相同name的排序
*/
@Data
static class Order{
/**排序方式(ASC/DESC)*/
private Sort.Direction sort;
/**排序的name*/
private String name;
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
Order order = (Order) o;
return name.equals(order.name);
}
@Override
public int hashCode() {
return Objects.hash(name);
}
}
}
public enum Behavior {
BW,//bwteen
EQ,//equal
GE,//greaterThanOrEqualTo
GT,//greaterThan
IN,
LE,//lessThanOrEqualTo
LK,//like
LT,//lessThan
NE,//not equal
NI,//not in
NL;//not like
}
/**
* 时间模板枚举
* 这里只添加了一个例子,如果需要扩展时间模板,请自行添加
*/
public enum DateFormat {
YEAR_MONTH_DAY_HOURS_MIN_SEC("yyyy-MM-dd HH:mm:ss");
private String dateFormat;
DateFormat(String dateFormat) {
this.dateFormat = dateFormat;
}
public String getDateFormat(){
return this.dateFormat;
}
}
{
"page":1,
"size":10,
"params":[{
"name":"xxx",
"params":["2018-12-21 11:07:44"],
"behavior":"EQ"
}],
"orders":[{
"sort":"DESC",
"name":"xx"
}]
}