import lombok.Getter;
import lombok.Setter;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import javax.persistence.criteria.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
/**
* @Author: Ma Chi
* @Date: 2019-05-22
* @Time: 16:05
* @ClassName: McSpecification
* @Description: 扩展Specification
*/
public class McSpecification<T> implements Specification<T> {
/**
* 属性分隔符
*/
private static final String PROPERTY_SEPARATOR = ".";
/**
* and条件组
*/
List<Cnd> andConditions = new ArrayList<>();
/**
* or条件组
*/
List<Cnd> orConditions = new ArrayList<>();
/**
* 排序条件组
*/
List<Order> orders = new ArrayList<>();
@Override
public Predicate toPredicate(Root<T> root, CriteriaQuery<?> cq, CriteriaBuilder cb) {
Predicate restrictions = cb.and(getAndPredicates(root, cb));
restrictions = cb.and(restrictions, getOrPredicates(root, cb));
cq.orderBy(getOrders(root, cb));
return restrictions;
}
/**
* 给里面传参,用Cnd里面得静态方法,可以传多个值
*
* @param conditions
* @return
*/
public McSpecification and(Cnd... conditions) {
for (Cnd condition : conditions) {
//循环全部添加到and条件组
andConditions.add(condition);
}
return this;
}
public McSpecification or(Collection<Cnd> conditions) {
//全添加到or条件组
orConditions.addAll(conditions);
return this;
}
public McSpecification desc(String property) {
this.orders.add(Order.desc(property));
return this;
}
public McSpecification asc(String property) {
this.orders.add(Order.asc(property));
return this;
}
/**
* 把and条件组得拼到一起
*
* @param root
* @param cb
* @return
*/
private Predicate getAndPredicates(Root<T> root, CriteriaBuilder cb) {
//过滤条件用Predicate方法拼接
Predicate restrictions = cb.conjunction();
for (Cnd condition : andConditions) {
if (condition == null) {
continue;
}
Path<?> path = this.getPath(root, condition.property);
if (path == null) {
continue;
}
switch (condition.operator) {
case eq://等于
if (condition.value != null) {
/**
* isAssignableFrom()方法是判断是否为某个类的父类,父类.class.isAssignableFrom(子类.class)
* instanceof关键字是判断是否某个类的子类。子类实例 instanceof 父类类型
*/
if (String.class.isAssignableFrom(path.getJavaType()) && condition.value instanceof String) {
if (!((String) condition.value).isEmpty()) {//判断condition.value 是否有元素
restrictions = cb.and(restrictions, cb.equal(path, condition.value));
}
} else {
restrictions = cb.and(restrictions, cb.equal(path, condition.value));
}
}
break;
case ge://大于等于
if (Number.class.isAssignableFrom(path.getJavaType()) && condition.value instanceof Number) {
if (!((String) condition.value).isEmpty()) {//判断condition.value 是否有元素
restrictions = cb.and(restrictions, cb.ge((Path<Number>) path, (Number) condition.value));
}
}
break;
case gt://大于
if (Number.class.isAssignableFrom(path.getJavaType()) && condition.value instanceof Number) {
if (!((String) condition.value).isEmpty()) {//判断condition.value 是否有元素
restrictions = cb.and(restrictions, cb.gt((Path<Number>) path, (Number) condition.value));
}
}
break;
case le://小于等于
if (Number.class.isAssignableFrom(path.getJavaType()) && condition.value instanceof Number) {
if (!((String) condition.value).isEmpty()) {//判断condition.value 是否有元素
restrictions = cb.and(restrictions, cb.le((Path<Number>) path, (Number) condition.value));
}
}
break;
case lt://小于
if (Number.class.isAssignableFrom(path.getJavaType()) && condition.value instanceof Number) {
if (!((String) condition.value).isEmpty()) {//判断condition.value 是否有元素
restrictions = cb.and(restrictions, cb.lt((Path<Number>) path, (Number) condition.value));
}
}
break;
case ne://不等于
if (condition.value != null) {
if (String.class.isAssignableFrom(path.getJavaType()) && condition.value instanceof String && !((String) condition.value).isEmpty()) {
restrictions = cb.and(restrictions, cb.notEqual(path, condition.value));
}
}
break;
case isNotNull:
restrictions = cb.and(restrictions, path.isNotNull());
break;
}
}
return restrictions;
}
private Predicate getOrPredicates(Root<T> root, CriteriaBuilder cb) {
Predicate restrictions = cb.conjunction();
for (Cnd condition : orConditions) {
if (condition == null) {
continue;
}
Path<?> path = this.getPath(root, condition.property);
if (path == null) {
continue;
}
switch (condition.operator) {
case eq://等于
if (condition.value != null) {
/**
* isAssignableFrom()方法是判断是否为某个类的父类,父类.class.isAssignableFrom(子类.class)
* instanceof关键字是判断是否某个类的子类。子类实例 instanceof 父类类型
*/
if (String.class.isAssignableFrom(path.getJavaType()) && condition.value instanceof String) {
if (!((String) condition.value).isEmpty()) {//判断condition.value 是否有元素
restrictions = cb.or(restrictions, cb.equal(path, condition.value));
}
} else {
restrictions = cb.or(restrictions, cb.equal(path, condition.value));
}
}
break;
case ge://大于等于
if (Number.class.isAssignableFrom(path.getJavaType()) && condition.value instanceof Number) {
if (!((String) condition.value).isEmpty()) {//判断condition.value 是否有元素
restrictions = cb.or(restrictions, cb.ge((Path<Number>) path, (Number) condition.value));
}
}
break;
case gt://大于
if (Number.class.isAssignableFrom(path.getJavaType()) && condition.value instanceof Number) {
if (!((String) condition.value).isEmpty()) {//判断condition.value 是否有元素
restrictions = cb.or(restrictions, cb.gt((Path<Number>) path, (Number) condition.value));
}
}
break;
case le://小于等于
if (Number.class.isAssignableFrom(path.getJavaType()) && condition.value instanceof Number) {
if (!((String) condition.value).isEmpty()) {//判断condition.value 是否有元素
restrictions = cb.or(restrictions, cb.le((Path<Number>) path, (Number) condition.value));
}
}
break;
case lt://小于
if (Number.class.isAssignableFrom(path.getJavaType()) && condition.value instanceof Number) {
if (!((String) condition.value).isEmpty()) {//判断condition.value 是否有元素
restrictions = cb.or(restrictions, cb.lt((Path<Number>) path, (Number) condition.value));
}
}
break;
case ne://不等于
if (condition.value != null) {
if (String.class.isAssignableFrom(path.getJavaType()) && condition.value instanceof String && !((String) condition.value).isEmpty()) {
restrictions = cb.or(restrictions, cb.notEqual(path, condition.value));
}
}
break;
case isNotNull:
restrictions = cb.or(restrictions, path.isNotNull());
break;
}
}
return restrictions;
}
/**
* 排序
*
* @param root
* @param cb
* @return
*/
private List<javax.persistence.criteria.Order> getOrders(Root<T> root, CriteriaBuilder cb) {
List<javax.persistence.criteria.Order> orderList = new ArrayList<>();
//CollectionUtils.isEmpty判断集合是否为空
if (orderList == null || CollectionUtils.isEmpty(orders)) {
return orderList;
}
for (Order order : orders) {
if (order == null) {
continue;
}
//获取属性
String property = order.getProperty();
//获取排序规则
Sort.Direction direction = order.getDirection();
Path<?> path = this.getPath(root, property);
if (path == null || direction == null) {
continue;
}
switch (direction) {
case ASC:
orderList.add(cb.asc(path));
break;
case DESC:
orderList.add(cb.desc(path));
break;
}
}
return orderList;
}
/**
* 获取path
*
* @param path
* @param propertyPath 属性路径
* @param <X>
* @return Path
*/
private <X> Path<X> getPath(Path<X> path, String propertyPath) {
if (path == null || StringUtils.isEmpty(propertyPath)) {
return (Path<X>) path;
}
//StringUtils.substringBefore 截取指定字符串(PROPERTY_SEPARATOR)之前的内容
String property = StringUtils.substringBefore(propertyPath, PROPERTY_SEPARATOR);
//StringUtils.substringAfter 截取指定字符串(PROPERTY_SEPARATOR)之后的内容
return getPath(path.get(property), StringUtils.substringAfter(propertyPath, PROPERTY_SEPARATOR));
}
/**
* 条件
*/
public static class Cnd {
Operator operator;//运算符
String property;//属性
Object value;//值
public Cnd(Operator operator, String property, Object value) {
this.operator = operator;
this.property = property;
this.value = value;
}
/**
* 相等
*
* @param property 属性
* @param value 值
* @return
*/
public static Cnd eq(String property, Object value) {
return new Cnd(Operator.eq, property, value);
}
/**
* 不相等
*
* @param property 属性
* @param value 值
* @return
*/
public static Cnd ne(String property, Object value) {
return new Cnd(Operator.ne, property, value);
}
/**
* 大于
*
* @param property 属性
* @param value 值
* @return
*/
public static Cnd gt(String property, Object value) {
return new Cnd(Operator.gt, property, value);
}
/**
* 小于
*
* @param property 属性
* @param value 值
* @return
*/
public static Cnd lt(String property, Object value) {
return new Cnd(Operator.lt, property, value);
}
/**
* 大于等于
*
* @param property 属性
* @param value 值
* @return
*/
public static Cnd ge(String property, Object value) {
return new Cnd(Operator.ge, property, value);
}
/**
* 小于等于
*
* @param property 属性
* @param value 值
* @return
*/
public static Cnd le(String property, Object value) {
return new Cnd(Operator.le, property, value);
}
/**
* 不为null
*
* @param property 属性
* @param value 值
* @return
*/
public static Cnd isNotNull(String property, Object value) {
return new Cnd(Operator.isNotNull, property, value);
}
}
/**
* 运算符
*/
public enum Operator {
/**
* 等于
*/
eq("="),
/**
* 不等于
*/
ne(" != "),
/**
* 大于
*/
gt(">"),
/**
* 小于
*/
lt("<"),
/**
* 大于等于
*/
ge(">="),
/**
* 小于等于
*/
le("<="),
/**
* 不为null
*/
isNotNull(" is not Null");
@Getter
@Setter
private String operator;
Operator(String operator) {
this.operator = operator;
}
}
/**
* 排序
*/
@Getter
@Setter
public static class Order {
private String property;//属性
private Sort.Direction direction = Sort.Direction.ASC;//方向
public Order(String property, Sort.Direction direction) {
this.property = property;
this.direction = direction;
}
/**
* @param property
* @return 递增序列,升序
*/
public static Order asc(String property) {
return new Order(property, Sort.Direction.ASC);
}
/**
* @param property
* @return 递减序列,逆序
*/
public static Order desc(String property) {
return new Order(property, Sort.Direction.DESC);
}
}
}
扩展Specification(新)
最新推荐文章于 2021-06-01 14:25:26 发布