扩展Specification(新)



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);
        }

    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

mcxiaochi

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值