SPring boot jpa 封装查询条件
最近使用spring data jpa做了两个项目,对于动态查询的不友好做了个类似hibernate的封装,记录也分享下
首先定义一个所有条件的容器,继承Specification
- /**
- * 定义一个查询条件容器
- * @author lee
- *
- * @param <T>
- */
- public class Criteria<T> implements Specification<T>{
- private List<Criterion> criterions = new ArrayList<Criterion>();
- public Predicate toPredicate(Root<T> root, CriteriaQuery<?> query,
- CriteriaBuilder builder) {
- 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
- * @Create In 2012-2-8 By lee
- * @param expression0 void
- */
- public void add(Criterion criterion){
- if(criterion!=null){
- criterions.add(criterion);
- }
- }
- }
然后是各种条件组装类,我首先做了一个接口来包装各种条件
- /**
- * 条件接口
- * 用户提供条件表达式接口
- * @Class Name Criterion
- * @Author lee
- * @Create In 2012-2-8
- */
- public interface Criterion {
- public enum Operator {
- EQ, NE, LIKE, GT, LT, GTE, LTE, AND, OR
- }
- public Predicate toPredicate(Root<?> root, CriteriaQuery<?> query,
- CriteriaBuilder builder);
- }
然后是针对不同类型条件处理的实现
一个是简单比较类型的处理
- /**
- * 简单条件表达式
- * @author lee
- *
- */
- public class SimpleExpression implements Criterion{
- private String fieldName; //属性名
- private Object value; //对应值
- private Operator operator; //计算符
- protected SimpleExpression(String fieldName, Object value, Operator operator) {
- this.fieldName = fieldName;
- this.value = value;
- this.operator = operator;
- }
- public String getFieldName() {
- return fieldName;
- }
- public Object getValue() {
- return value;
- }
- public Operator getOperator() {
- return operator;
- }
- @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:
- 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;
- }
- }
- }
一个逻辑条件计算实现
- /**
- * 逻辑条件表达式 用于复杂条件时使用,如但属性多对应值的OR查询等
- * @author lee
- *
- */
- public class LogicalExpression implements Criterion {
- private Criterion[] criterion; // 逻辑表达式中包含的表达式
- private Operator operator; //计算符
- public LogicalExpression(Criterion[] criterions, Operator operator) {
- this.criterion = criterions;
- this.operator = operator;
- }
- public Predicate toPredicate(Root<?> root, CriteriaQuery<?> query,
- CriteriaBuilder builder) {
- List<Predicate> predicates = new ArrayList<Predicate>();
- 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()]));
- default:
- return null;
- }
- }
- }
添加一个组装工厂类
- /**
- * 条件构造器
- * 用于创建条件表达式
- * @Class Name Restrictions
- * @Author lee
- */
- public class Restrictions {
- /**
- * 等于
- * @param fieldName
- * @param value
- * @param ignoreNull
- * @return
- */
- public static SimpleExpression eq(String fieldName, Object value, boolean ignoreNull) {
- if(StringUtils.isEmpty(value))return null;
- return new SimpleExpression (fieldName, value, Operator.EQ);
- }
- /**
- * 不等于
- * @param fieldName
- * @param value
- * @param ignoreNull
- * @return
- */
- public static SimpleExpression ne(String fieldName, Object value, boolean ignoreNull) {
- if(StringUtils.isEmpty(value))return null;
- return new SimpleExpression (fieldName, value, Operator.NE);
- }
- /**
- * 模糊匹配
- * @param fieldName
- * @param value
- * @param ignoreNull
- * @return
- */
- public static SimpleExpression like(String fieldName, String value, boolean ignoreNull) {
- if(StringUtils.isEmpty(value))return null;
- return new SimpleExpression (fieldName, value, Operator.LIKE);
- }
- /**
- *
- * @param fieldName
- * @param value
- * @param matchMode
- * @param ignoreNull
- * @return
- */
- public static SimpleExpression like(String fieldName, String value,
- MatchMode matchMode, boolean ignoreNull) {
- if(StringUtils.isEmpty(value))return null;
- return null;
- }
- /**
- * 大于
- * @param fieldName
- * @param value
- * @param ignoreNull
- * @return
- */
- public static SimpleExpression gt(String fieldName, Object value, boolean ignoreNull) {
- if(StringUtils.isEmpty(value))return null;
- return new SimpleExpression (fieldName, value, Operator.GT);
- }
- /**
- * 小于
- * @param fieldName
- * @param value
- * @param ignoreNull
- * @return
- */
- public static SimpleExpression lt(String fieldName, Object value, boolean ignoreNull) {
- if(StringUtils.isEmpty(value))return null;
- return new SimpleExpression (fieldName, value, Operator.LT);
- }
- /**
- * 大于等于
- * @param fieldName
- * @param value
- * @param ignoreNull
- * @return
- */
- public static SimpleExpression lte(String fieldName, Object value, boolean ignoreNull) {
- if(StringUtils.isEmpty(value))return null;
- return new SimpleExpression (fieldName, value, Operator.GTE);
- }
- /**
- * 小于等于
- * @param fieldName
- * @param value
- * @param ignoreNull
- * @return
- */
- public static SimpleExpression gte(String fieldName, Object value, boolean ignoreNull) {
- if(StringUtils.isEmpty(value))return null;
- return new SimpleExpression (fieldName, value, Operator.LTE);
- }
- /**
- * 并且
- * @param criterions
- * @return
- */
- public static LogicalExpression and(Criterion... criterions){
- return new LogicalExpression(criterions, Operator.AND);
- }
- /**
- * 或者
- * @param criterions
- * @return
- */
- public static LogicalExpression or(Criterion... criterions){
- return new LogicalExpression(criterions, Operator.OR);
- }
- /**
- * 包含于
- * @param fieldName
- * @param value
- * @return
- */
- @SuppressWarnings("rawtypes")
- public static LogicalExpression in(String fieldName, Collection value, boolean ignoreNull) {
- if(ignoreNull&&(value==null||value.isEmpty())){
- return null;
- }
- 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);
- }
- }
使用方法如下
- Criteria<Event> c = new Criteria<Event>();
- c.add(Restrictions.like("code", searchParam.getCode(), true));
- c.add(Restrictions.eq("level", searchParam.getLevel(), false));
- c.add(Restrictions.eq("mainStatus", searchParam.getMainStatus(), true));
- c.add(Restrictions.eq("flowStatus", searchParam.getFlowStatus(), true));
- c.add(Restrictions.eq("createUser.userName", searchParam.getCreateUser(), true));
- c.add(Restrictions.lte("submitTime", searchParam.getStartSubmitTime(), true));
- c.add(Restrictions.gte("submitTime", searchParam.getEndSubmitTime(), true));
- c.add(Restrictions.eq("needFollow", searchParam.getIsfollow(), true));
- c.add(Restrictions.ne("flowStatus", CaseConstants.CASE_STATUS_DRAFT, true));
- c.add(Restrictions.in("solveTeam.code",teamCodes, true));
- eventDao.findAll(c);
其中eventDao为继承JpaSpecificationExecutor的接口类
SPring boot jpa 封装查询条件的更多相关文章
- Spring Boot JPA的查询语句
文章目录 准备工作 Containing, Contains, IsContaining 和 Like StartsWith EndsWith 大小写不敏感 Not @Query Spring Boo ...
- spring boot jpa 复杂查询 动态查询 连接and和or 模糊查询 分页查询
最近项目中用到了jpa,刚接触的时候有些激动,以前的到层忽然不用写sql不用去自己实现了,只是取个方法名就实现了,太惊艳了,惊为天人,但是慢慢的就发现不是这么回事了,在动态查询的时候,不知道怎么操作了 ...
- 【Spring Data 系列学习】Spring Data JPA 自定义查询,分页,排序,条件查询
Spring Boot Jpa 默认提供 CURD 的方法等方法,在日常中往往时无法满足我们业务的要求,本章节通过自定义简单查询案例进行讲解. 快速上手 项目中的pom.xml.application ...
- Spring Boot 入门系列(二十七)使用Spring Data JPA 自定义查询如此简单,完全不需要写SQL!
前面讲了Spring Boot 整合Spring Boot JPA,实现JPA 的增.删.改.查的功能.JPA使用非常简单,只需继承JpaRepository ,无需任何数据访问层和sql语句即可实现 ...
- Spring NamedParameterJdbcTemplate命名参数查询条件封装, NamedParameterJdbcTemplate查询封装
Spring NamedParameterJdbcTemplate命名参数查询条件封装, NamedParameterJdbcTemplate查询封装 >>>>>> ...
- 序列化表单为json对象,datagrid带额外参提交一次查询 后台用Spring data JPA 实现带条件的分页查询 多表关联查询
查询窗口中可以设置很多查询条件 表单中输入的内容转为datagrid的load方法所需的查询条件向原请求地址再次提出新的查询,将结果显示在datagrid中 转换方法看代码注释 <td cols ...
- Spring Boot(五):Spring Boot Jpa 的使用
在上篇文章Spring Boot(二):Web 综合开发中简单介绍了一下 Spring Boot Jpa 的基础性使用,这篇文章将更加全面的介绍 Spring Boot Jpa 常见用法以及注意事项. ...
- Spring Boot Jpa 的使用
Spring Boot Jpa 介绍 首先了解 Jpa 是什么? Jpa (Java Persistence API) 是 Sun 官方提出的 Java 持久化规范.它为 Java 开发人员提供了一种 ...
- (转)Spring Boot(五):Spring Boot Jpa 的使用
http://www.ityouknow.com/springboot/2016/08/20/spring-boot-jpa.html 在上篇文章Spring Boot(二):Web 综合开发中简单介 ...
随机推荐
- python27期day14:有参装饰器、多个装饰器装饰一个函数、递归、作业题
1.有参装饰器:给装饰器添加一个参数.来控制装饰器的行为. @auth(参数) auth里层的函数名 = auth(参数) 被装饰的函数名 = auth里层的函数名(被装饰的函数名) 被装饰的函数名( ...
- Vue (表单、斗篷、条件、循环指令,分隔符成员、计算属性成员、属性的监听、vue组件、子组件、各个常见的钩子函数)
表单指令 <!DOCTYPE html> <html lang="zh"> <head> <meta charset="UTF- ...
- SLAM:
十四讲: 传感器约束了外部环境 测到的通常都是一些间接的物理量而不是直接的位置数据 只能通过一些间接的手段,从这些数据推算自己的位置 好处是没有对环境提出任何要求 camera:单目.双目.深度 Mo ...
- [RN] windows7 安装 Realm Studio 后,打开报错 A JavaScript error occurred in the main process
windows7 安装 Realm Studio 后,打开报错 报错如下: A JavaScript error occurred in the main process Uncaught Exce ...
- [HNOI2002] Kathy 函数
数位 DP 套路题,求二进制下区间内回文串个数. 设 dp[][][] 表示到第几位时,是否为回文数,去掉前导零后共几位.之后到边界时判断是否为回文数计入贡献. 一开始不知道答案统计要高精,于是后来就 ...
- C++中二分法之upper_bound()、lower_bound、binary_search()函数
前言 数组.容器vector都适用,在头文件"algorithm"中 下面的例子是针对容器的,注意返回的是距离元素3最近的指针it,输出的是*it结果为元素4,假如我想得到位置而非 ...
- machine_math
1.导数与函数的凹凸性关系: 从下往上看,如果函数是凸出来的就是凸函数,如果是凹的就是凹函数. 函数的凹凸性是二阶函数来判断的. 如果二阶函数大于零,那么就是凸函数,否则就是凹函数. 2.一阶导数为零 ...
- [LeetCode] 888. Fair Candy Swap 公平糖果交换
Alice and Bob have candy bars of different sizes: A[i] is the size of the i-th bar of candy that Ali ...
- 微信小程序之页面打开数量限制
无论是在小程序还是APP中,打开一个页面其实就是创建了一个新的View对象,一层层叠加的.当点击页面的回退按钮就是把当前页面关闭. 这个过程中会涉及到一个问题,就是打开页面的数量.在某些设计下,比如一 ...
- 仅逗oier们一笑(不定期更新中)(update.2019年12月8日)
CCF的正确解释: //部分来自:朝阳的二愣子的CSDN博客.ydclyq 的博客 .拱垲的博客.Randolph's Blog. 编译下列程序,会有意想不到的惊喜哦(注意打开声音): #includ ...