美文网首页
springdata中Specification查询封装

springdata中Specification查询封装

作者: whoismy8023 | 来源:发表于2017-10-26 15:11 被阅读0次

    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()
    

    相关文章

      网友评论

          本文标题:springdata中Specification查询封装

          本文链接:https://www.haomeiwen.com/subject/mbrkpxtx.html