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

目录
  • JPA 通过Specification实现复杂查询
    • 下面就简单介绍一下Specification的使用
  • spring-data-jpa Specification拼接复杂查询

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来组建条件查询语句

上图是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;
    }

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • Spring data jpa的使用与详解(复杂动态查询及分页,排序)

    一. 使用Specification实现复杂查询 (1) 什么是Specification Specification是springDateJpa中的一个接口,他是用于当jpa的一些基本CRUD操作的扩展,可以把他理解成一个spring jpa的复杂查询接口.其次我们需要了解Criteria 查询,这是是一种类型安全和更面向对象的查询.而Spring Data JPA支持JPA2.0的Criteria查询,相应的接口是JpaSpecificationExecutor. 而JpaSpecifica

  • JPA多条件复杂SQL动态分页查询功能

    概述 ORM映射为我们带来便利的同时,也失去了较大灵活性,如果SQL较复杂,要进行动态查询,那必定是一件头疼的事情(也可能是lz还没发现好的方法),记录下自己用的三种复杂查询方式. 环境 springBoot IDEA2017.3.4 JDK8 pom.xml <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0&q

  • Spring Data JPA实现动态查询的两种方法

    前言 一般在写业务接口的过程中,很有可能需要实现可以动态组合各种查询条件的接口.如果我们根据一种查询条件组合一个方法的做法来写,那么将会有大量方法存在,繁琐,维护起来相当困难.想要实现动态查询,其实就是要实现拼接SQL语句.无论实现如何复杂,基本都是包括select的字段,from或者join的表,where或者having的条件.在Spring Data JPA有两种方法可以实现查询条件的动态查询,两种方法都用到了Criteria API. Criteria API 这套API可用于构建对数据

  • JPA的多表复杂查询的方法示例

    最近工作中由于要求只能用hibernate+jpa 与数据库进行交互,在简单查询中,jpa继承CrudRepository接口 ,然后利用jpa的方法命名规范进行jpql查询,然而在进行复杂查询时,需要继承JpaSpecificationExecutor接口 利用Specification 进行复杂查询,由于我自己就遇到了这一问题,查了好多资料,虽然有方法,但是都没有一个详细的讲解,以至于知道方法而不能很好的利用jpa复杂查询的方便之处.我将举几个栗子,来详细的说一下我自己在使用jpa多表复杂查

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

    目录 JPA 通过Specification实现复杂查询 下面就简单介绍一下Specification的使用 spring-data-jpa Specification拼接复杂查询 JPA 通过Specification实现复杂查询 JPA中继承BaseRepo之后,可以使用最基本的增删改查,如果想实现复杂查询,则需要借助Specification来完成这个功能: 下面就简单介绍一下Specification的使用 public void findAll(ConstructPlanPageReq

  • Spring Data JPA实现动态条件与范围查询实例代码

    Spring Data JPA为我们提供了Query With Example来实现动态条件查询,当查询条件为空的时候,我们不用做大量的条件判断.但是Query With Example却不支持范围查询(包括日期范围,数值范围查询),本文通过Specification实现了既支持动态条件查询又支持范围查询的方法. 1 实现方式 1.1 范围对象Range定义 import java.io.Serializable; public class Range<E> implements Serial

  • JPA如何使用findBy方法自定义查询

    目录 JPA使用findBy方法自定义查询 在JPA中使用findBy方法自定义查询 在postman测试请求的接口如下 JPA的findBy语法整理 前提操作 JPA中支持的关键词 JPA使用findBy方法自定义查询 最近在项目中使用spring boot+jpa的方式来访问数据库,例如:本项目中的课程目录详情表中包括了外键课程详情ID,想通过课程详情ID查找出所有关联的课程目录详情 在JPA中使用findBy方法自定义查询 在postman测试请求的接口如下 这样就很方便的查询所需要的数据

  • JPA原生SQL(自定义SQL)分页查询逻辑详解

    目录 JPA原生SQL(自定义SQL)分页查询 经过测试下面方法可以 pageable对象里定义排序的字段 JPA原生SQL分页查询踩坑记录 1.问题简述 2.解决方案 JPA原生SQL(自定义SQL)分页查询 JPA自己写SQL查询的话,分页还稍微麻烦 经过测试下面方法可以 @Query(nativeQuery = true, value = "select * from goods where " + " codeName like CONCAT('%',?1,'%')

  • Spring Data JPA 复杂/多条件组合分页查询

    话不多说,请看代码: public Map<String, Object> getWeeklyBySearch(final Map<String, String> serArgs, String pageNum, String pageSize) throws Exception { // TODO Auto-generated method stub Map<String,Object> resultMap=new HashMap<String, Object&

  • springdata jpa使用Example快速实现动态查询功能

    目录 Example官方介绍 Example api的组成 限制 使用 测试查询 自定匹配器规则 补充 官方创建ExampleMatcher例子(1.8 lambda) StringMatcher 参数 总结 Example官方介绍 Query by Example (QBE) is a user-friendly querying technique with a simple interface. It allows dynamic query creation and does not r

  • spring data jpa 创建方法名进行简单查询方式

    目录 最常见的做法是 按照规范创建查询方法 支持的规范表达式 spring data jpa 可以通过在接口中按照规定语法创建一个方法进行查询,spring data jpa 基础接口中,如CrudRepository中findOne,save,delete等,那么我们自己怎么按照需要创建一个方法进行查询呢? 最常见的做法是 声明一个接口继承于CrudRepository 或者 PagingAndSortingRepository,JpaRepository,Repository public

  • Jpa Specification如何实现and和or同时使用查询

    目录 同时使用and和or的查询 JPA 动态查询之AND.OR结合使用 问题描述 代码示例 同时使用and和or的查询 UserServiceImpl 类,service实现类 import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.jpa.domain.Specificat

  • jpa多条件查询重写Specification的toPredicate方法

    目录 Criteria查询基本概念 Criteria查询基本对象的构建 下面我们用两个示例代码来更深入的了解 Spring Data JPA支持JPA2.0的Criteria查询,相应的接口是JpaSpecificationExecutor. Criteria 查询:是一种类型安全和更面向对象的查询 . 这个接口基本是围绕着Specification接口来定义的, Specification接口中只定义了如下一个方法: Predicate toPredicate(Root<T> root, C

  • spring data jpa分页查询示例代码

    最近项目上用就hibernate+spring data jpa,一开始感觉还不错,但是随着对业务的复杂,要求处理一些复杂的sql,就顺便研究了下,把结果记录下,以便日后查看.用到Specification,需要继承JpaSpecificationExecutor接口.(下面代码有的分页从0开始作为第一页,有的从1开始作为作为第一页,我也忘记,请自己测试) DAO层: import java.util.List; import org.springframework.data.domain.Pa

随机推荐