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 implements Specification {

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

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

    @Override
    public Predicate toPredicate(Root 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 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 {

    /**
     * 条件列表
     */
    private List 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 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 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 add(String key, SpecificationOperator.Operator operator, Object value) {
        return this.add(SpecificationOperator.Join.and, key, operator, value);
    }

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

package com.lky.commons.specification;

/**
 * 操作符类,这个类中存储了键值对和操作符号,另外存储了连接下一个条件的类型是and还是or
 * 
* 创建时通过 id>=7,其中id就是key,>=就是operator操作符,7就是value *
* 特殊的自定义几个操作符(:表示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 builder = new SimpleSpecificationBuilder<>();
builder.add("createTime", SpecificationOperator.Operator.between, new Date[]{beginDate, date});
List userList = userService.findAll(builder.generateSpecification());
System.out.println("0------------------" + userList.size());

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

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

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

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

//实例代码使用一
SimpleSpecificationBuilder 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 categoryList = categoryService.findAll(builder.generateSpecification());

//实例代码使用二
SimpleSpecificationBuilder 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 userMessageList = userMessageService.findAll(builder.generateSpecification(), pageable);         

你可能感兴趣的:(spring-data-jpa 简单查询:封装及使用)