1、操作符类:
package net.sppan.base.service.specification;
/**
* 操作符类,这个类中存储了键值对和操作符号,另外存储了连接下一个条件的类型是and还是or
* <br>
* 创建时通过 id>=7,其中id就是key,>=就是oper操作符,7就是value
* <br>
* 特殊的自定义几个操作符(:表示like %v%,b:表示v%,:b表示%v)
*/
public class SpecificationOperator {
/**
* 操作符的key,如查询时的name,id之类
*/
private String key;
/**
* 操作符的value,具体要查询的值
*/
private Object value;
/**
* 操作符,自己定义的一组操作符,用来方便查询
*/
private String oper;
/**
* 连接的方式:and或者or
*/
private String join;
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public Object getValue() {
return value;
}
public void setValue(Object value) {
this.value = value;
}
public String getOper() {
return oper;
}
public void setOper(String oper) {
this.oper = oper;
}
public String getJoin() {
return join;
}
public void setJoin(String join) {
this.join = join;
}
public static enum Operator {
eq, ge, le, gt, lt, likeL, likeR, likeAll, isNull, isNotNull, notEqual;
@Override
public String toString() {
return name();
}
}
public static enum Join {
and, or;
@Override
public String toString() {
return name();
}
}
}
Specification实现类:
package net.sppan.base.service.specification;
import net.sppan.base.service.specification.SpecificationOperator.Join;
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;
public class SimpleSpecification<T> implements Specification<T> {
/**
* 查询的条件列表,是一组列表
* */
private List<SpecificationOperator> opers;
public SimpleSpecification(List<SpecificationOperator> opers) {
this.opers = opers;
}
@Override
public Predicate toPredicate(Root<T> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
int index = 0;
//通过resultPre来组合多个条件
Predicate resultPre = null;
for(SpecificationOperator op:opers) {
if(index++==0) {
resultPre = generatePredicate(root,criteriaBuilder,op);
continue;
}
Predicate pre = generatePredicate(root,criteriaBuilder,op);
if(pre==null) continue;
if(Join.and.name().equalsIgnoreCase(op.getJoin())) {
resultPre = criteriaBuilder.and(resultPre,pre);
} else if(Join.or.name().equalsIgnoreCase(op.getJoin())) {
resultPre = criteriaBuilder.or(resultPre,pre);
}
}
return resultPre;
}
private Predicate generatePredicate(Root<T> root,CriteriaBuilder criteriaBuilder, SpecificationOperator op) {
/*
* 根据不同的操作符返回特定的查询*/
if(SpecificationOperator.Operator.eq.name().equalsIgnoreCase(op.getOper())) {
return criteriaBuilder.equal(root.get(op.getKey()),op.getValue());
} else if(SpecificationOperator.Operator.ge.name().equalsIgnoreCase(op.getOper())) {
return criteriaBuilder.ge(root.get(op.getKey()).as(Number.class), (Number)op.getValue());
} else if(SpecificationOperator.Operator.le.name().equalsIgnoreCase(op.getOper())) {
return criteriaBuilder.le(root.get(op.getKey()).as(Number.class),(Number)op.getValue());
} else if(SpecificationOperator.Operator.gt.name().equalsIgnoreCase(op.getOper())) {
return criteriaBuilder.gt(root.get(op.getKey()).as(Number.class),(Number)op.getValue());
} else if(SpecificationOperator.Operator.lt.name().equalsIgnoreCase(op.getOper())) {
return criteriaBuilder.lt(root.get(op.getKey()).as(Number.class),(Number)op.getValue());
} else if(SpecificationOperator.Operator.likeAll.name().equalsIgnoreCase(op.getOper())) {
return criteriaBuilder.like(root.get(op.getKey()).as(String.class),"%"+op.getValue()+"%");
} else if(SpecificationOperator.Operator.likeL.name().equalsIgnoreCase(op.getOper())) {
return criteriaBuilder.like(root.get(op.getKey()).as(String.class),op.getValue()+"%");
} else if(SpecificationOperator.Operator.likeR.name().equalsIgnoreCase(op.getOper())) {
return criteriaBuilder.like(root.get(op.getKey()).as(String.class),"%"+op.getValue());
} else if(SpecificationOperator.Operator.isNull.name().equalsIgnoreCase(op.getOper())) {
return criteriaBuilder.isNull(root.get(op.getKey()));
} else if(SpecificationOperator.Operator.isNotNull.name().equalsIgnoreCase(op.getOper())) {
return criteriaBuilder.isNotNull(root.get(op.getKey()));
} else if(SpecificationOperator.Operator.notEqual.name().equalsIgnoreCase(op.getOper())) {
return criteriaBuilder.notEqual(root.get(op.getKey()),op.getValue());
}
return null;
}
}
查询条件构造类:
package net.sppan.base.service.specification;
import java.util.ArrayList;
import java.util.List;
import net.sppan.base.service.specification.SpecificationOperator.Join;
import org.springframework.data.jpa.domain.Specification;
public class SimpleSpecificationBuilder<T> {
/**
* 条件列表
*/
private List<SpecificationOperator> opers;
/**
* 构造函数,初始化的条件是and
*/
public SimpleSpecificationBuilder(String key,String oper,Object value) {
SpecificationOperator so = new SpecificationOperator();
so.setJoin(Join.and.name());
so.setKey(key);
so.setOper(oper);
so.setValue(value);
opers = new ArrayList<SpecificationOperator>();
opers.add(so);
}
public SimpleSpecificationBuilder() {
opers = new ArrayList<SpecificationOperator>();
}
/**
* 完成条件的添加
* @return
*/
public SimpleSpecificationBuilder<T> add(String key,String oper,Object value,String join) {
SpecificationOperator so = new SpecificationOperator();
so.setKey(key);
so.setValue(value);
so.setOper(oper);
so.setJoin(join);
opers.add(so);
return this;
}
/**
* 添加or条件的重载
* @return this,方便后续的链式调用
*/
public SimpleSpecificationBuilder<T> addOr(String key,String oper,Object value) {
return this.add(key,oper,value,Join.or.name());
}
/**
* 添加and的条件
* @return
*/
public SimpleSpecificationBuilder<T> add(String key,String oper,Object value) {
return this.add(key,oper,value,Join.and.name());
}
public Specification<T> generateSpecification() {
Specification<T> specification = new SimpleSpecification<T>(opers);
return specification;
}
}
使用方式:
SimpleSpecificationBuilder<Resource> builder = new SimpleSpecificationBuilder<Resource>();//Resource 持久层实体
builder.add("name", Operator.likeAll.name(), "keyword");
Specification specification = builder.generateSpecification()