简单查询条件封装
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);