您的位置:首页 > 编程语言 > Java开发

SpringDataJPA 查询封装

2016-11-16 11:37 561 查看
GITHUB地址

用过JPA查询应该都知道,实现下面接口去做查询是很痛苦的,简单的业务逻辑却要写几十行的代码,因此开始查阅各种资料,最终看了一位博主的文章后开始在他的基础上继续完善

@Override
public Predicate toPredicate(Root<User> root, CriteriaQuery<?> query, CriteriaBuilder cb) {


封装过程是参照Hibernate QBC查询做的,会QBC的同学就会这个的使用方法了,以下是一些例子,还有很多方法可以自己体验一下,如果不是做关联查询目前的功能可以涵盖大部分操作了

@Autowired
private UserRepository userRepository;

@Test
public void getTObjectJson() {
Criteria<User> criteria = new Criteria<>();
criteria.add(Restrictions.eq("name", "test")); //等于 name = ‘test’
criteria.add(Restrictions.like("name", "test", Criterion.MatchMode.ANYWHERE)); //等于 name like %test%
criteria.add(Restrictions.between("age", 1 , 20));  //age between(1, 20)
criteria.add(Restrictions.isNotEmpty("name")); // ISNOTEMPTY(name)
List<String> list = new ArrayList();
list.add("Alice");
list.add("Mick");
criteria.add(Restrictions.in("name", list));  // name in ('Alice','Mick')

criteria.add(Restrictions.eq(Projections.Length("name"), 5));  // length(name) = 5
criteria.add(Restrictions.gt(Projections.Max("name"), 5));  // max(name) = 5
criteria.add(Restrictions.or(Restrictions.eq("name", "tt"),Restrictions.eq("name", "qq"))); //(name = 'tt' or name = 'qq')
List<User> userList = userRepository.findAll(criteria);
}


以下是封装代码,当时项目急用所以封装的挺粗糙的,谈不上代码美观高效。望勿怪,但是还蛮好用的,一年多了一直在用,如果有好的建议也希望能提出来,不过该封装有个问题,就是不能实现多表联查,这个挺头疼的。

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

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.apache.commons.lang.StringUtils;
import org.springframework.data.jpa.domain.Specification;
/**
* 定义一个查询条件容器
*
* @param <T>
*/
public class Criteria<T> implements Specification<T>{
//查询条件容器
private List<Criterion> criterions = new ArrayList<Criterion>();
//倒序查询条件
private String orderByDESC;
//升序查询条件
private String orderByASC;
//group查询条件
private String groupBy;

public Predicate toPredicate(Root<T> root, CriteriaQuery<?> query,
CriteriaBuilder builder) {
if(!StringUtils.isEmpty(orderByASC))
query.orderBy(builder.desc(root.get(getOrderByASC())));
if(!StringUtils.isEmpty(orderByDESC))
query.orderBy(builder.desc(root.get(getOrderByDESC())));
if(!StringUtils.isEmpty(groupBy))
query.groupBy(root.get(getGroupBy()));
if (!criterions.isEmpty()) {
List<Predicate> predicates = new ArrayList<Predicate>();
for(Criterion c : criterions){
predicates.add(c.toPredicate(root, query,builder));
}
// 将所有条件用 and 联合起来
if (predicates.size() > 0) {
return builder.and(predicates.toArray(new Predicate[predicates.size()]));
}
}
return builder.conjunction();
}
/**
* 增加简单条件表达式
* @Methods Name add
*
*/
public void add(Criterion criterion){
if(criterion!=null){
criterions.add(criterion);
}
}

public void orderByDESC(String col){
setOrderByDESC(col);
}

public void orderByASC(String col){
setOrderByASC(col);
}

public void groupBy(String col){
setGroupBy(col);
}

public String getOrderByDESC() {
return orderByDESC;
}
private void setOrderByDESC(String orderByDESC) {
this.orderByDESC = orderByDESC;
}
public String getOrderByASC() {
return orderByASC;
}
private void setOrderByASC(String orderByASC) {
this.orderByASC = orderByASC;
}
public String getGroupBy() {
return groupBy;
}
private void setGroupBy(String groupBy) {
this.groupBy = groupBy;
}


import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
/**
* 条件接口
* 用户提供条件表达式接口
*/
public interface Criterion {
public enum Operator {
EQ, NE, LIKE, GT, LT, GTE, LTE, AND, OR, BETWEEN, ISNULL, ISNOTNULL, ISEMPTY, ISNOTEMPTY
}

public enum MatchMode {
START, END, ANYWHERE
}

public enum Projection {
MAX, MIN, AVG, LENGTH, SUM, COUNT
}

public Predicate toPredicate(Root<?> root, CriteriaQuery<?> query,
CriteriaBuilder builder);
}
import java.util.ArrayList;
import java.util.List;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Expression;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.springframework.util.StringUtils;

/**
* 逻辑条件表达式 用于复杂条件时使用,如但属性多对应值的OR查询等
*
*/
public class LogicalExpression implements Criterion {
private Criterion[] criterion;  // 逻辑表达式中包含的表达式
private Operator operator;      //计算符
private String col;
private Object exp1;
private Object exp2;

public LogicalExpression(Criterion[] criterions, Operator operator) {
this.criterion = criterions;
this.operator = operator;
}

//between用构造方法
public LogicalExpression(String col, Object exp1, Object exp2, Operator operator){
this.col = col;
this.exp1 = exp1;
this.exp2 = exp2;
this.operator = operator;
this.criterion = null;
}

public Predicate toPredicate(Root<?> root, CriteriaQuery<?> query,
CriteriaBuilder builder) {
List<Predicate> predicates = new ArrayList<Predicate>();
if(!StringUtils.isEmpty(criterion))
for(int i=0;i<this.criterion.length;i++){
predicates.add(this.criterion[i].toPredicate(root, query, builder));
}
switch (operator) {
case OR:
return builder.or(predicates.toArray(new Predicate[predicates.size()]));
case AND:
return builder.and(predicates.toArray(new Predicate[predicates.size()]));
case BETWEEN:
Expression expression = root.get(col);
return builder.between(expression, (Comparable) exp1, (Comparable) exp2);
default:
return null;
}
}

public String getCol() {
return col;
}

public Object getExp1() {
return exp1;
}

public Object getExp2() {
return exp2;
}
}
/**
* 函数条件构造器
*/
public class Projection{
//函数作用字段
private String col;
//函数类型
private Criterion.Projection type;

public Projection(String col, Criterion.Projection type){
this.col = col;
this.type = type;
}

public String getCol() {
return col;
}

public Criterion.Projection getType() {
return type;
}

}
import javax.persistence.criteria.CriteriaBuil
4000
der;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Expression;
import javax.persistence.criteria.Path;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.apache.commons.lang.StringUtils;

/**
* 函数条件表达式
*/
public class ProjectionExpression implements Criterion {
private String fieldName;       //属性名
private Object value;           //对应值
private Projection projection;  //函数条件类型
private Operator operator;      //基础条件类型
private MatchMode matchMode;    //like用匹配类型

protected ProjectionExpression(String fieldName, Object value, Projection projection, Operator operator) {
this.fieldName = fieldName;
this.value = value;
this.projection = projection;
this.operator = operator;
}
protected ProjectionExpression(String fieldName, Object value, Projection projection, Operator operator, MatchMode matchMode) {
this.fieldName = fieldName;
this.value = value;
this.projection = projection;
this.operator = operator;
this.matchMode = matchMode;
}

@SuppressWarnings({ "rawtypes", "unchecked" })
public Predicate toPredicate(Root<?> root, CriteriaQuery<?> query,
CriteriaBuilder builder) {
Path expression = null;
if(fieldName.contains(".")){
String[] names = StringUtils.split(fieldName, ".");
expression = root.get(names[0]);
for (int i = 1; i < names.length; i++) {
expression = expression.get(names[i]);
}
}else{
expression = root.get(fieldName);
}
switch (projection) {
case LENGTH :
return getBuilder(builder, builder.length(expression), value, matchMode);
case MAX :
return getBuilder(builder, builder.max(expression), value, matchMode);
case SUM :
return getBuilder(builder, builder.sum(expression), value, matchMode);
case MIN :
return getBuilder(builder, builder.min(expression), value, matchMode);
case AVG :
return getBuilder(builder, builder.avg(expression), value, matchMode);
case COUNT :
return getBuilder(builder, builder.count(expression), value, matchMode);
default:
return null;
}
}

private Predicate getBuilder(CriteriaBuilder builder, Expression expression, Object obj, MatchMode matchMode){
switch (operator) {
case EQ:
return builder.equal(expression, value);
case NE:
return builder.notEqual(expression, value);
case LIKE:
switch(matchMode){
case START :
return builder.like((Expression<String>) expression, value + "%");
case END :
return builder.like((Expression<String>) expression, "%" + value);
case ANYWHERE :
return builder.like((Expression<String>) expression, "%" + value + "%");
default :
return builder.like((Expression<String>) expression, "%" + value + "%");
}
case LT:
return builder.lessThan(expression, (Comparable) value);
case GT:
return builder.greaterThan(expression, (Comparable) value);
case LTE:
return builder.lessThanOrEqualTo(expression, (Comparable) value);
case GTE:
return builder.greaterThanOrEqualTo(expression, (Comparable) value);
default:
return null;
}
}

public String getFieldName() {
return fieldName;
}
public Object getValue() {
return value;
}
public Projection getProjection() {
return projection;
}
public Operator getOperator() {
return operator;
}
public MatchMode getMatchMode() {
return matchMode;
}
}
计算器用类
/*
* 计算用类
* */
public class Projections {

public static Projection Max(String col){
return new Projection(col,  Criterion.Projection.MAX);
}

public static Projection Length(String col){
return new Projection(col, Criterion.Projection.LENGTH);
}

public static Projection Min(String col){
return new Projection(col, Criterion.Projection.MIN);
}

public static Projection Sum(String col){
return new Projection(col, Criterion.Projection.SUM);
}

}

import java.util.Collection;
import static com.scistor.label.jpa.Criterion.MatchMode;
import static com.scistor.label.jpa.Criterion.Operator;
/**
* 条件构造器
* 用于创建条件表达式
*/
public class Restrictions {

/**
* 不为空
* @param fieldName : 匹配字段
* @return
*/
public static SimpleExpression isNotEmpty(String fieldName) {
return new SimpleExpression (fieldName, Operator.ISNOTEMPTY);
}

/**
* 为空
* @param fieldName : 匹配字段
* @return
*/
public static SimpleExpression isEmpty(String fieldName) {
return new SimpleExpression (fieldName, Operator.ISEMPTY);
}

/**
* 为空
* @param fieldName : 匹配字段
* @return
*/
public static SimpleExpression isNull(String fieldName) {
return new SimpleExpression (fieldName, Operator.ISNULL);
}

/**
* 不为空
* @param fieldName : 匹配字段
* @return
*/
public static SimpleExpression isNotNull(String fieldName) {
return new SimpleExpression (fieldName, Operator.ISNOTNULL);
}

/**
* 等于
* @param fieldName : 匹配字段
* @param value : 匹配值
* @return
*/
public static SimpleExpression eq(String fieldName, Object value) {
if(value.equals(null))return null;
return new SimpleExpression (fieldName, value, Operator.EQ);
}

/**
* 等于 (函数条件查询)
* @param projection : Projection查询条件(Projections.MAX\SUM\AVG...)
* @param value : 匹配值
* @return
*/
public static ProjectionExpression eq(Projection projection, Object value) {
if(value.equals(null))return null;
return new ProjectionExpression (projection.getCol(), value, projection.getType(), Operator.EQ);
}

/**
* 不等于
* @param fieldName : 匹配字段
* @param value : 匹配值
* @return
*/
public static SimpleExpression ne(String fieldName, Object value) {
if(value.equals(null))return null;
return new SimpleExpression (fieldName, value, Operator.NE);
}

/**
* 不等于(函数条件查询)
* @param projection : Projection查询条件(Projections.MAX\SUM\AVG...)
* @param value : 匹配值
* @return
*/
public static ProjectionExpression ne(Projection projection, Object value) {
if(value.equals(null))return null;
return new ProjectionExpression (projection.getCol(), value, projection.getType(), Operator.NE);
}

/**
* 模糊匹配
* @param fieldName : 匹配字段
* @param value : 匹配值
* @return
*/
public static SimpleExpression like(String fieldName, String value) {
if(value.equals(null))return null;
return new SimpleExpression (fieldName, value, Operator.LIKE);
}

/**
* 模糊匹配 (函数条件查询)
* @param projection : Projection查询条件(Projections.MAX\SUM\AVG...)
* @param value : 匹配值
* @return
*/
public static ProjectionExpression like(Projection projection, String value) {
if(value.equals(null))return null;
return new ProjectionExpression (projection.getCol(), value, projection.getType(), Operator.LIKE);
}

/**
*  自定义模式模糊匹配
* @param fieldName : 匹配字段
* @param value : 匹配值
* @param matchMode : 匹配方式(MatchMode.START\END\ANYWHERE)
* @return
*/
public static SimpleExpression like(String fieldName, String value,
MatchMode matchMode) {
if(value.equals(null))return null;
return new SimpleExpression(fieldName, value, matchMode, Operator.LIKE);
}

/**
*  自定义模式模糊匹配(函数条件查询)
* @param projection : Projection查询条件(Projections.MAX\SUM\AVG...)
* @param value  : 匹配值
* @param matchMode : 匹配方式(MatchMode.START\END\ANYWHERE)
* @return
*/
public static ProjectionExpression like(Projection projection, String value,
MatchMode matchMode) {
if(value.equals(null))return null;
return new ProjectionExpression (projection.getCol(), value, projection.getType(), Operator.LIKE, matchMode);
}

/**
* 大于
* @param fieldName : 匹配字段
* @param value : 匹配值
* @return
*/
public static SimpleExpression gt(String fieldName, Object value) {
if(value.equals(null))return null;
return new SimpleExpression (fieldName, value, Operator.GT);
}

/**
* 大于(函数条件查询)
* @param projection : Projection查询条件(Projections.MAX\SUM\AVG...)
* @param value : 匹配值
* @return
*/
public static ProjectionExpression gt(Projection projection, Object value) {
if(value.equals(null))return null;
return new ProjectionExpression (projection.getCol(), value, projection.getType(), Operator.GT);
}

/**
* 小于
* @param fieldName : 匹配字段
* @param value : 匹配值
* @return
*/
public static SimpleExpression lt(String fieldName, Object value) {
if(value.equals(null))return null;
return new SimpleExpression (fieldName, value, Operator.LT);
}

/**
* 小于(函数条件查询)
* @param projection : Projection查询条件(Projections.MAX\SUM\AVG...)
* @param value : 匹配值
* @return
*/
public static ProjectionExpression lt(Projection projection, Object value) {
if(value.equals(null))return null;
return new ProjectionExpression (projection.getCol(), value, projection.getType(), Operator.LT);
}

/**
* 小于等于
* @param fieldName : 匹配字段
* @param value : 匹配值
* @return
*/
public static SimpleExpression lte(String fieldName, Object value) {
if(value.equals(null))return null;
return new SimpleExpression (fieldName, value, Operator.LTE);
}

/**
* 小于等于(函数条件查询)
* @param projection : Projection查询条件(Projections.MAX\SUM\AVG...)
* @param value : 匹配值
* @return
*/
public static ProjectionExpression lte(Projection projection, Object value) {
if(value.equals(null))return null;
return new ProjectionExpression (projection.getCol(), value, projection.getType(), Operator.LTE);
}

/**
* 大于等于
* @param fieldName : 匹配字段
* @param value : 匹配值
* @return
*/
public static SimpleExpression gte(String fieldName, Object value) {
if(value.equals(null))return null;
return new SimpleExpression (fieldName, value, Operator.GTE);
}

/**
* 大于等于
* @param projection : Projection查询条件(Projections.MAX\SUM\AVG...)
* @param value : 匹配值
* @return
*/
public static ProjectionExpression gte(Projection projection, Object value) {
if(value.equals(null))return null;
return new ProjectionExpression (projection.getCol(), value, projection.getType(), Operator.GTE);
}

/**
* 或者
* @param criterions
* @return
*/
public static LogicalExpression or(Criterion... criterions){
return new LogicalExpression(criterions, Operator.OR);
}

/**
* 区间
* @param column : 匹配字段
* @param1 val1 左区间
* @param2 val2 右区间
* @return
*/
public static LogicalExpression between(String column, Object val1, Object val2){
return new LogicalExpression(column, val1, val2, Operator.BETWEEN);
}

/**
* 包含于
* @param fieldName : 匹配字段
* @param value : 匹配值
* @return
*/
@SuppressWarnings("rawtypes")
public static LogicalExpression in(String fieldName, Collection value) {
SimpleExpression[] ses = new SimpleExpression[value.size()];
int i=0;
for(Object obj : value){
ses[i]=new SimpleExpression(fieldName,obj,Operator.EQ);
i++;
}
return new LogicalExpression(ses,Operator.OR);
}

/**
* 包含于
* @param fieldName : 匹配字段
* @param value : 匹配值
* @return
*/
@SuppressWarnings("rawtypes")
public static LogicalExpression notIn(String fieldName, Collection value) {
SimpleExpression[] ses = new SimpleExpression[value.size()];
int i=0;
for(Object obj : value){
ses[i]=new SimpleExpression(fieldName,obj,Operator.NE);
i++;
}
return new LogicalExpression(ses,Operator.AND);
}

}

/**
* 简单条件表达式
*/
public class SimpleExpression implements Criterion {
private String fieldName;       //属性名
private Object value;           //对应值
private Operator operator;      //计算符
private MatchMode matchMode;    //like匹配方式

protected SimpleExpression(String fieldName, Operator operator) {
this.fieldName = fieldName;
this.operator = operator;
}

protected SimpleExpression(String fieldName, Object value, Operator operator) {
this.fieldName = fieldName;
this.value = value;
this.operator = operator;
}

protected SimpleExpression(String fieldName, Object value, MatchMode matchMode, Operator operator) {
this.fieldName = fieldName;
this.value = value;
this.operator = operator;
this.matchMode = matchMode;
}

public String getFieldName() {
return fieldName;
}
public Object getValue() {
return value;
}
public Operator getOperator() {
return operator;
}
public MatchMode getMatchMode() {
return matchMode;
}

@SuppressWarnings({ "rawtypes", "unchecked" })
public Predicate toPredicate(Root<?> root, CriteriaQuery<?> query,
CriteriaBuilder builder) {
Path expression = null;
if(fieldName.contains(".")){
String[] names = StringUtils.split(fieldName, ".");
expression = root.get(names[0]);
for (int i = 1; i < names.length; i++) {
expression = expression.get(names[i]);
}
}else{
expression = root.get(fieldName);
}

switch (operator) {
case EQ:
return builder.equal(expression, value);
case NE:
return builder.notEqual(expression, value);
case LIKE:
switch(matchMode){
case START :
return builder.like((Expression<String>) expression, value + "%");
case END :
return builder.like((Expression<String>) expression, "%" + value);
case ANYWHERE :
return builder.like((Expression<String>) expression, "%" + value + "%");
default :
return builder.like((Expression<String>) expression, "%" + value + "%");
}
case LT:
return builder.lessThan(expression, (Comparable) value);
case GT:
return builder.greaterThan(expression, (Comparable) value);
case LTE:
return builder.lessThanOrEqualTo(expression,
b3d6
(Comparable) value);
case GTE:
return builder.greaterThanOrEqualTo(expression, (Comparable) value);
case ISNOTNULL:
return builder.isNotNull(expression);
case ISNULL:
return builder.isNull(expression);
case ISEMPTY:
return builder.isEmpty(expression);
case ISNOTEMPTY:
return builder.isNotEmpty(expression);
default:
return null;
}
}
}

以上就是所有需要用的类了,可以把他们放在一个包里打成jar包用比较方便
JPA查询接口, 实体类就不贴了,看一下springboot实体类就好了
import com.scistor.label.auth.model.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.PagingAndSortingRepository;

import java.util.List;

public interface UserRepository extends JpaSpecificationExecutor<User>, JpaRepository<User, String>, PagingAndSortingRepository<User, String> {

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  jpa springboot