JPA 通过Specification如何实现复杂查询


Posted in Java/Android onNovember 23, 2021

JPA 通过Specification实现复杂查询

JPA中继承BaseRepo之后,可以使用最基本的增删改查,如果想实现复杂查询,则需要借助Specification来完成这个功能:

下面就简单介绍一下Specification的使用

public void findAll(ConstructPlanPageReqEntity constructPlanPageReqEntity) {
	Integer pageNum = page.getPageNum();
        Integer pageSize = page.getPageSize();
        String costType = constructPlanPageReqEntity.getCostType();
        String name = constructPlanPageReqEntity.getName();
        String planMoneyStart = constructPlanPageReqEntity.getPlanMoneyStart();
        String planMoneyEnd = constructPlanPageReqEntity.getPlanMoneyEnd();
        String singMoneyEnd = constructPlanPageReqEntity.getSingMoneyEnd();
        String signMoneyStart = constructPlanPageReqEntity.getSignMoneyStart();
        long projectId = Long.parseLong(constructPlanPageReqEntity.getProjectId());
        String status = constructPlanPageReqEntity.getStatus();
        //分页
        pageNum=pageNum-1;
        Pageable pageable = PageRequest.of(pageNum, pageSize);
//多条件匹配查询
        Specification specification= new Specification<ContractPlanBean>() {
            @Override
            public Predicate toPredicate(Root<ContractPlanBean> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                ArrayList<Predicate> list = new ArrayList<>();
                Path<String> costType1 = root.get("costType");
                Path<String> name1 = root.get("name");
                Path<Long> projectId1 = root.get("projectId");
                Path<Object> status1 = root.get("status");
                if (projectId>0){
                    list.add(criteriaBuilder.equal(projectId1,projectId));
                }
                if (StringUtil.isNotEmpty(status)){
                    list.add(criteriaBuilder.equal(status1,status));
                }
                //条件查询
                if (StringUtil.isNotEmpty(costType)){
                    list.add(criteriaBuilder.equal(costType1,costType));
                }
                //模糊查询
                if (StringUtil.isNotEmpty(name)){
                    list.add(criteriaBuilder.like(name1,"%"+name+"%"));
                }
                //范围查询
                if (StringUtil.isNotEmpty(planMoneyStart)&&StringUtil.isNotEmpty(planMoneyEnd)){
                    try {
                        list.add(criteriaBuilder.between(root.get("planMoney"),NumberUtil.strToDouble(planMoneyStart),NumberUtil.strToDouble(planMoneyEnd)));
                    } catch (Exception e) {
                        throw new ApiException("规划金额查询失败");
                    }
                }
                 //排序
                criteriaQuery.orderBy(criteriaBuilder.asc(root.get("name")));
                Predicate[] array = new Predicate[list.size()];
                return criteriaBuilder.and(list.toArray(array));
            }
        };
}

以上代码实现了多条件查询,其中需要重写toPredicate方法,具体参数:

  • 用root.get()获取bean中的数据库对应字段
  • 用criteriaBuilder来组建条件查询语句

JPA 通过Specification如何实现复杂查询

上图是criteriaBuilder各种sql符号的方法名,根据需求组建不同的sql语句

criteriaBuilder.and(list.toArray(array))这句是最后定义各个sql查询条件的关系,这里用的and

至此,复杂sql语句就拼接完成,本人对Specification的使用未进行深入研究,个人觉得相对filter Strem的复杂查询来说Specification更繁琐,因此更倾向于通过Strem的复杂查询,这回就不多说了,下次就介绍下如何使用Stream进行复杂查询

spring-data-jpa Specification拼接复杂查询

public Page<ServiceItem> findAll(Map<String, String[]> params, ServiceItemConsumeStatus serviceItemConsumeStatus,ServiceItemStatus serviceItemStatus, Pageable pageable) {
        return dao.findAll(spec(serviceItemConsumeStatus, serviceItemStatus, params), pageable);
    }
    private Specification<ServiceItem> spec(final ServiceItemConsumeStatus serviceItemConsumeStatus, 
    final ServiceItemStatus serviceItemStatus, Map<String, String[]> params) {
        Collection<SearchFilter> filters = SearchFilter.parse(params).values();
        final Specification<ServiceItem> fsp = SearchFilter.spec(filters, ServiceItem.class);
        Specification<ServiceItem> sp = new Specification<ServiceItem>() {
            public Predicate toPredicate(Root<ServiceItem> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                Predicate pred = fsp.toPredicate(root, query, cb);
                if (ServiceItemConsumeStatus.可消费.equals(serviceItemConsumeStatus)) {
                    pred = cb.and(pred, cb.gt(root.get("countLeft").as(int.class), 0));
                } else if (ServiceItemConsumeStatus.消费完毕.equals(serviceItemConsumeStatus)) {
                    pred = cb.and(pred, cb.le(root.get("countLeft").as(int.class), 0));
                }
                if (serviceItemStatus != null) {
                    pred = cb.and(pred, cb.equal(root.get("status"), serviceItemStatus));
                }
                return pred;
            }
        };
        return sp;
    }

以上为个人经验,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Java/Android 相关文章推荐
教你用Java在个人电脑上实现微信扫码支付
Jun 13 Java/Android
idea搭建可运行Servlet的Web项目
Jun 26 Java/Android
分析Java中Map的遍历性能问题
Jun 26 Java/Android
Java集成swagger文档组件
Jun 28 Java/Android
Java图书管理系统,课程设计必用(源码+文档)
Jun 30 Java/Android
mybatis中注解与xml配置的对应关系和对比分析
Aug 04 Java/Android
alibaba seata服务端具体实现
Feb 24 Java/Android
Java实现学生管理系统(IO版)
Feb 24 Java/Android
关于EntityWrapper的in用法
Mar 22 Java/Android
Java 写一个简单的图书管理系统
Apr 26 Java/Android
java开发双人五子棋游戏
May 06 Java/Android
Android基础入门之dataBinding的简单使用教程
Jun 21 Java/Android
Java使用JMeter进行高并发测试
Java 在线考试云平台的实现
OpenCV实现反阈值二值化
聊聊SpringBoot自动装配的魔力
Nov 17 #Java/Android
Springboot如何同时装配两个相同类型数据库
Nov 17 #Java/Android
OpenCV实现普通阈值
聊聊Lombok中的@Builder注解使用教程
Nov 17 #Java/Android
You might like
WAR3重制版DOTA 5V5初体验
2020/04/09 DOTA
简体中文转换为繁体中文的PHP函数
2006/10/09 PHP
队列在编程中的实际应用(php)
2010/09/04 PHP
jQuery EasyUI API 中文文档 - DateBox日期框
2011/10/15 PHP
基于PHP实现用户注册登录功能
2016/10/14 PHP
PHP编程中的Session阻塞问题与解决方法分析
2017/08/07 PHP
解决PhpStorm64不能启动的问题
2020/06/20 PHP
Javascript 中介者模式实例
2009/12/16 Javascript
获取offsetTop和offsetLeft值的js代码(兼容)
2013/04/16 Javascript
js获取当前路径的简单示例代码
2014/01/08 Javascript
js跨域请求数据的3种常用的方法
2015/12/01 Javascript
巧用canvas
2017/01/21 Javascript
详解VueJs异步动态加载块
2017/03/09 Javascript
JS利用正则表达式实现简单的密码强弱判断实例
2017/06/16 Javascript
JavaScript脚本语言是什么_动力节点Java学院整理
2017/06/26 Javascript
使用D3.js制作图表详解
2017/08/13 Javascript
Vue Element 分组+多选+可搜索Select选择器实现示例
2018/07/23 Javascript
详解webpack 热更新优化
2018/09/13 Javascript
Python查看多台服务器进程的脚本分享
2014/06/11 Python
python实现根据窗口标题调用窗口的方法
2015/03/13 Python
python生成器generator用法实例分析
2015/06/04 Python
详解Python函数式编程—高阶函数
2019/03/29 Python
Python Switch Case三种实现方法代码实例
2020/06/18 Python
超级实用的8个Python列表技巧
2020/08/24 Python
美国顶级户外凉鞋品牌:Chacos
2017/03/27 全球购物
关联、聚合(Aggregation)以及组合(Composition)的区别
2012/02/29 面试题
什么是抽象
2015/12/13 面试题
JavaScript实现页面动态验证码的实现示例
2021/03/23 Javascript
中医药大学毕业生自荐信
2013/11/08 职场文书
长安大学毕业生自我鉴定
2014/01/17 职场文书
计划生育宣传标语
2014/06/21 职场文书
办护照工作证明
2014/10/01 职场文书
2014年就业工作总结
2014/11/26 职场文书
初中信息技术教学计划
2015/01/22 职场文书
《赵州桥》教学反思
2016/02/17 职场文书
详解apache编译安装httpd-2.4.54及三种风格的init程序特点和区别
2022/07/15 Servers