spring-data-jpa 简单查询:封装及使用

简单查询条件封装

package com.lky.commons.specification;

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.Collection;
import java.util.Date;
import java.util.List;

/**
 * 简单条件表达式
 *
 * @author luckyhua
 * @version 1.0
 * @since 2017/9/19
 */
public class SimpleSpecification<T> implements Specification<T> {

    /**
     * 查询的条件列表,是一组列表
     */
    private List<SpecificationOperator> operators;

    public SimpleSpecification(List<SpecificationOperator> operators) {
        this.operators = operators;
    }

    @Override
    public Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
        int index = 0;
        //通过resultPre来组合多个条件
        Predicate resultPre = null;
        for (SpecificationOperator op : operators) {
            if (index++ == 0) {
                resultPre = generatePredicate(root, cb, op);
                continue;
            }
            Predicate pre = generatePredicate(root, cb, op);
            if (pre == null) {
                continue;
            }
            switch (op.getJoin()) {
                case and:
                    resultPre = cb.and(resultPre, pre);
                    break;
                case or:
                    resultPre = cb.or(resultPre, pre);
                    break;
                default:
            }
        }
        return resultPre;
    }

    /**
     * 根据不同的操作符返回特定的查询
     *
     * @param root root
     * @param cb   条件构造器
     * @param op   操作对象
     * @return 逻辑表达式
     */
    private Predicate generatePredicate(Root<T> root, CriteriaBuilder cb, SpecificationOperator op) {
        Object value = op.getValue();
        switch (op.getOperator()) {
            case eq:
                return cb.equal(root.get(op.getKey()), value);
            case ne:
                return cb.notEqual(root.get(op.getKey()), value);
            case ge:
                return cb.ge(root.get(op.getKey()).as(Number.class), (Number) value);
            case le:
                return cb.le(root.get(op.getKey()).as(Number.class), (Number) value);
            case gt:
                return cb.gt(root.get(op.getKey()).as(Number.class), (Number) value);
            case lt:
                return cb.lt(root.get(op.getKey()).as(Number.class), (Number) value);
            case in:
                if (value instanceof Collection) {
                    return root.get(op.getKey()).in((Collection) value);
                }
                return root.get(op.getKey()).in(value);
            case notIn:
                if (value instanceof Collection) {
                    return cb.not(root.get(op.getKey()).in((Collection) value));
                }
                return cb.not(root.get(op.getKey()).in(value));
            case likeAll:
                return cb.like(root.get(op.getKey()).as(String.class), "%" + value + "%");
            case likeL:
                return cb.like(root.get(op.getKey()).as(String.class), value + "%");
            case likeR:
                return cb.like(root.get(op.getKey()).as(String.class), "%" + value);
            case isNull:
                return cb.isNull(root.get(op.getKey()));
            case isNotNull:
                return cb.isNotNull(root.get(op.getKey()));
            case lessThan:
                if (value instanceof Date) {
                    return cb.lessThan(root.get(op.getKey()), (Date) value);
                }
            case lessThanEqual:
                if (value instanceof Date) {
                    return cb.lessThanOrEqualTo(root.get(op.getKey()), (Date) value);
                }
            case greaterThan:
                if (value instanceof Date) {
                    return cb.greaterThan(root.get(op.getKey()), (Date) value);
                }
            case greaterThanEqual:
                if (value instanceof Date) {
                    return cb.greaterThanOrEqualTo(root.get(op.getKey()), (Date) value);
                }
            case between:
                if (value instanceof Date[]) {
                    Date[] dateArray = (Date[]) value;
                    return cb.between(root.get(op.getKey()), dateArray[0], dateArray[1]);
                }
            default:
                return null;
        }
    }
}

package com.lky.commons.specification;

import org.springframework.data.jpa.domain.Specification;

import java.util.ArrayList;
import java.util.List;

/**
 * 条件构造器
 * 用于创建条件表达式
 *
 * @author luckyhua
 * @version 1.0
 * @since 2017/9/19
 */
public class SimpleSpecificationBuilder<T> {

    /**
     * 条件列表
     */
    private List<SpecificationOperator> operators;

    public SimpleSpecificationBuilder() {
        operators = new ArrayList<>();
    }

    /**
     * 构造函数,初始化的条件是and
     *
     * @param key      条件的建
     * @param operator 条件
     * @param value    条件的值
     * @return 添加完的条件
     */
    public SimpleSpecificationBuilder(String key, SpecificationOperator.Operator operator, Object value) {
        SpecificationOperator so = new SpecificationOperator();
        so.setJoin(SpecificationOperator.Join.and);
        so.setKey(key);
        so.setOperator(operator);
        so.setValue(value);
        operators = new ArrayList<>();
        operators.add(so);
    }

    /**
     * 完成条件的添加
     *
     * @param join     连接符
     * @param key      条件的建
     * @param operator 条件
     * @param value    条件的值
     * @return this,方便后续的链式调用
     */
    public SimpleSpecificationBuilder<T> add(SpecificationOperator.Join join, String key, SpecificationOperator.Operator operator, Object value) {
        SpecificationOperator so = new SpecificationOperator();
        so.setJoin(join);
        so.setKey(key);
        so.setValue(value);
        so.setOperator(operator);
        operators.add(so);
        return this;
    }

    /**
     * 添加or条件
     *
     * @param key      条件的建
     * @param operator 条件
     * @param value    条件的值
     * @return this,方便后续的链式调用
     */
    public SimpleSpecificationBuilder<T> addOr(String key, SpecificationOperator.Operator operator, Object value) {
        return this.add(SpecificationOperator.Join.or, key, operator, value);
    }

    /**
     * 添加and条件
     *
     * @param key      条件的建
     * @param operator 条件
     * @param value    条件的值
     * @return this,方便后续的链式调用
     */
    public SimpleSpecificationBuilder<T> add(String key, SpecificationOperator.Operator operator, Object value) {
        return this.add(SpecificationOperator.Join.and, key, operator, value);
    }

    /**
     * 构建条件表达式
     *
     * @return 表达式
     */
    public Specification<T> generateSpecification() {
        return new SimpleSpecification<>(operators);
    }
}

package com.lky.commons.specification;

/**
 * 操作符类,这个类中存储了键值对和操作符号,另外存储了连接下一个条件的类型是and还是or
 * <br>
 * 创建时通过 id>=7,其中id就是key,>=就是operator操作符,7就是value
 * <br>
 * 特殊的自定义几个操作符(:表示like %v%,b:表示v%,:b表示%v)
 *
 * @author luckyhua
 * @version 1.0
 * @since 2017/9/19
 */
public class SpecificationOperator {

    /**
     * 操作符的key,如查询时的name,id之类
     */
    private String key;

    /**
     * 操作符的value,具体要查询的值
     */
    private Object value;

    /**
     * 操作符,自己定义的一组操作符,用来方便查询
     */
    private Operator operator;

    /**
     * 连接的方式:and或者or
     */
    private Join 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 Operator getOperator() {
        return operator;
    }

    public void setOperator(Operator operator) {
        this.operator = operator;
    }

    public Join getJoin() {
        return join;
    }

    public void setJoin(Join join) {
        this.join = join;
    }

    public enum Operator {
        eq, ne, ge, le, gt, lt, likeL, likeR, likeAll, isNull, isNotNull, in, notIn,
        lessThan, lessThanEqual, greaterThan, greaterThanEqual, between;

        @Override
        public String toString() {
            return name();
        }
    }

    public enum Join {
        and, or;

        @Override
        public String toString() {
            return name();
        }
    }
}

简单查询条件使用

//测试between
Date date = new Date();
Date beginDate = DateUtils.getBeginDate(date, DAY_OF_YEAR);
SimpleSpecificationBuilder<User> builder = new SimpleSpecificationBuilder<>();
builder.add("createTime", SpecificationOperator.Operator.between, new Date[]{beginDate, date});
List<User> userList = userService.findAll(builder.generateSpecification());
System.out.println("0------------------" + userList.size());

//测试in
Set<Integer> idSet = new HashSet<>();
idSet.add(1);
idSet.add(2);
idSet.add(1999);
SimpleSpecificationBuilder<User> builder1 = new SimpleSpecificationBuilder<>();
builder1.add("id", SpecificationOperator.Operator.in, idSet);
List<User> userList1 = userService.findAll(builder1.generateSpecification());
System.out.println("1------------------" + userList1.size());

//测试not in
SimpleSpecificationBuilder<User> builder2 = new SimpleSpecificationBuilder<>();
builder2.add("id", SpecificationOperator.Operator.notIn, 1);
List<User> userList2 = userService.findAll(builder2.generateSpecification());
System.out.println("2------------------" + userList2.size());

//测试lessThanEqual
SimpleSpecificationBuilder<User> builder3 = new SimpleSpecificationBuilder<>();
builder3.add("createTime", SpecificationOperator.Operator.lessThanEqual, beginDate);
List<User> userList3 = userService.findAll(builder3.generateSpecification());
System.out.println("3------------------" + userList3.size());

//测试like
SimpleSpecificationBuilder<SUser> builder4 = new SimpleSpecificationBuilder<>();
builder4.add("username", SpecificationOperator.Operator.likeAll, "l");
List<SUser> sUserList = sUserDao.findAll(builder4.generateSpecification());
sUserList.forEach(sUser -> System.out.println(sUser.getUsername()));

//实例代码使用一
SimpleSpecificationBuilder<Category> builder = new SimpleSpecificationBuilder<>();
if (StringUtils.isNotEmpty(name)) {
    builder.add("name", SpecificationOperator.Operator.likeAll, name.trim());
}
if (parentId != null) {
    builder.add("parentId", SpecificationOperator.Operator.eq, parentId);
} else {
    builder.add("parentId", SpecificationOperator.Operator.isNull, null);
}
List<Category> categoryList = categoryService.findAll(builder.generateSpecification());

//实例代码使用二
SimpleSpecificationBuilder<UserMessage> builder = new SimpleSpecificationBuilder<>();
        builder.add("userId", SpecificationOperator.Operator.eq, user.getId());
if (StringUtils.isNotEmpty(type)) {
    builder.add("targetType", SpecificationOperator.Operator.eq, type);
}
if (StringUtils.isNotEmpty(title)) {
    builder.add("title", SpecificationOperator.Operator.likeAll, title);
}
Sort sort = new Sort(
        new Sort.Order(Sort.Direction.DESC, "unread"),
        new Sort.Order(Sort.Direction.DESC, "id"));
Pageable pageable = new PageRequest(pageNumber, pageSize, sort);
Page<UserMessage> userMessageList = userMessageService.findAll(builder.generateSpecification(), pageable);         
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容