SpringDataJPA 查询封装
2016-11-16 11:37
561 查看
GITHUB地址
用过JPA查询应该都知道,实现下面接口去做查询是很痛苦的,简单的业务逻辑却要写几十行的代码,因此开始查阅各种资料,最终看了一位博主的文章后开始在他的基础上继续完善
封装过程是参照Hibernate QBC查询做的,会QBC的同学就会这个的使用方法了,以下是一些例子,还有很多方法可以自己体验一下,如果不是做关联查询目前的功能可以涵盖大部分操作了
以下是封装代码,当时项目急用所以封装的挺粗糙的,谈不上代码美观高效。望勿怪,但是还蛮好用的,一年多了一直在用,如果有好的建议也希望能提出来,不过该封装有个问题,就是不能实现多表联查,这个挺头疼的。
用过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> { }
相关文章推荐
- SpringDataJPA学习记录(三)--复杂查询的封装
- SpringDataJPA学习记录(三)--复杂查询的封装
- SpringDataJPA学习记录(三)--复杂查询的封装
- spring data jpa 动态查询(工具类封装)
- spring data jpa的动态查询封装(转)
- Spring data JPA中使用Specifications动态构建查询
- spring-data-jpa Specification 拼接复杂查询
- 基于JPA规范的spring-data-jpa面向对象的查询方法举例
- SpringDataJpa的Specification查询
- Spring Data JPA 动态查询
- spring data jpa 利用@Query进行查询
- Spring Data Jpa 自定义属性查询规则
- Srping Data Jpa条件查询封装
- Spring Data Jpa 查询返回自定义对象
- 转载 spring-data-jpa 介绍 复杂查询,包括多表关联,分页,排序等
- spring data jpa 利用JpaSpecificationExecutor做复杂查询
- Spring data JPA中使用Specifications动态构建查询
- Spring Data JPA 复杂/多条件组合查询
- spring data jpa specification的封装
- Spring data jpa高级查询,部分字段查询,过滤查询,空字符过滤