相信熟悉Hibernate的人对于ORM给编程带来的便利于快捷一定不陌生,相对于MyBatis等需要编写复杂的SQL语句,ORM映射为我们带来的便利显而易见。但是,在获得便利的同时,失去的便是灵活性,这里不是说Hibernate不灵活,只是针对初学者来说,要掌握灵活的技巧,需要的成本相对较高。过去的半年里,在项目中通过Spring Cloud实现了一套关于为服务的基础架构,其中在数据持久层采用的是Spring Data JPA,对于曾经用过Hibernate的人来说,选择JPA会十分容易上手,因为语法一切都是那么熟悉。但是,在涉及到复杂的查询的时候,尤其是多条件查询的时候,如果通过命名方式实现,长长的方法名将是代码显得十分的不优雅。这个时候,大多数人会选择使用NativeQuery,通过编写SQL语句来实现,这种方式导致的结果就是项目代码中遍地是SQL,随着时间的推移,项目已经失去了使用JPA的初衷。能否有一种方式,在保障JPQL的风格里完成这种复杂的查询呢?这里介绍一种简单的方式:JpaSpecificationExecutor

  JpaSpecificationExecutor不属于JpaRepository体系,它允许自定义查询条件实现查询。通过源码可以发现,JpaSpecificationExecutor提供了如下几个方法:

  public interface JpaSpecificationExecutor<T> {

  T findOne(Specification<T> spec);

  List<T> findAll(Specification<T> spec);

  Page<T> findAll(Specification<T> spec, Pageable pageable);

  List<T> findAll(Specification<T> spec, Sort sort);

  long count(Specification<T> spec);

  }

  其中,Page<T> findAll(Specification<T> spec, Pageable pageable)是不是看起来很熟悉,因为在JpaRepository我们用的十分常见,只不过这里的入参不同,Pageable提供了排序分页的功能,Specification允许我们自定义查询条件,继续进入源码:

public interface Specification<T> {

  Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder cb);

}

没错,这个接口提供了唯一方法toPredicate,通过该方法构造出一个复杂查询条件。Root代表的是实体,CriteriaBuilder是条件构造器,通过该方法,我们构造出复杂的查询条件并返回,JPA便会自动的处理转换查询。下面以一个小demo描述使用JpaSpecificationExecutor实现复杂查询的步骤:

1、DAO层继承JpaSpecificationExecutor接口(当然,如果需要JpaRepository相关方法,同时继承即可)

@Component
public interface SpeciRepository extends JpaSpecificationExecutor<TestVO>,JpaRepository<TestVO, Long>{
}

2、Service构造查询条件,并调用DAO层

@Service

@Transactional

public class MySpeciServiceImpl implements MySpeciService {

    @Autowired  private SpeciRepository speciRepository;

  @Override  public Page<TestVO> findByPageAndParams(final TestVO param, int pageNumber,int pageSize) {

    Pageable pageable=new PageRequest(pageNumber, pageSize);  //分页信息

    Specification<TestVO> spec = new Specification<TestVO>() {        //查询条件构造

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

        Path<String> name = root.get("name");

        Path<Integer> age = root.get("age");

        Predicate p1 = cb.like(name, "%"+param.getName()+"%");

        Predicate p2 = cb.lt(age, param.getAge());

       Predicate p = cb.and(p1, p2);

         return p;

       }

     };

    return speciRepository.findAll(spec, pageable);

   }

}

通过以上两个步骤,就能实现一个基本的复杂分页查询,其实很简单。其中的关键点就是查询条件的构造,可以通过CriteriaBuilder提供的相关谓词进行组装。详细用法这里不累述,有兴趣或有需要可自行baidu。

JPA实现复杂条件分页查询的更多相关文章

  1. springboot jpa mongodb 多条件分页查询

    public Page<Recorded> getRecordeds(Integer page, Integer size, Recorded recorded) { if (page&l ...

  2. asp.net mvc多条件+分页查询解决方案

    开发环境vs2010 css:bootstrap js:jquery bootstrap paginator 原先只是想做个mvc的分页,但是一般的数据展现都需要检索条件,而且是多个条件,所以就变成了 ...

  3. 【java】spring-data-jpa 集成hibernate实现多条件分页查询

    初次接触spring-data-jpa,实现多条件分页查询. 基础环境 Spring Boot+spring-data-jpa+hibernate+mysql 1.接口 要继承这个接口,这个接口提供了 ...

  4. thinkphp 带条件分页查询

    thinkphp 带条件分页查询:form表单传值时候,method='get'. 用 get 传值

  5. 项目一:第四天 1、快递员的条件分页查询-noSession,条件查询 2、快递员删除(逻辑删除) 3、基于Apache POI实现批量导入区域数据 a)Jquery OCUpload上传文件插件使用 b)Apache POI读取excel文件数据

    1. 快递员的条件分页查询-noSession,条件查询 2. 快递员删除(逻辑删除) 3. 基于Apache POI实现批量导入区域数据 a) Jquery OCUpload上传文件插件使用 b) ...

  6. ASPNETCOREAPI 跨域处理 SQL 语句拼接 多条件分页查询 ASPNET CORE 核心 通过依赖注入(注入服务)

    ASPNETCOREAPI 跨域处理 AspNetCoreApi 跨域处理 如果咱们有处理过MV5 跨域问题这个问题也不大. (1)为什么会出现跨域问题:  浏览器安全限制了前端脚本跨站点的访问资源, ...

  7. JPA分页查询与条件分页查询

    情有独钟的JPA 平时在写一些小项目时,比较喜欢引用 Spring Data Jpa,其实还是图他写代码快~在日常的开发工作中,分页列表查询基本是随处可见,下面一起看一下如何使用 jpa 进行多条件查 ...

  8. jpa自定义条件分页查询

    主要依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>sp ...

  9. 【spring data jpa】带有条件的查询后分页和不带条件查询后分页实现

    一.不带有动态条件的查询 分页的实现 实例代码: controller:返回的是Page<>对象 @Controller @RequestMapping(value = "/eg ...

随机推荐

  1. 前端vue系列-起始篇 vue的基本认知

    hi,大家伙,我是佛系大大,很高兴与你们一起沟通,学习,进步. 很久不更新博客了,现在回来再写博客,尽然是有些怀念的感觉,幸福的感觉.因为写博客,内心会很宁静,沉浸在自己的世界中,是很幸福的一件事.当 ...

  2. java工作流引擎Jflow流程事件和流程节点事件设置

    流程实例的引入和设置 关键词: 开源工作流引擎  Java工作流开发  .net开源工作流引擎   流程事件 工作流节点事件 应用场景: 在一些复杂的业务逻辑流程中需要在某个节点或者是流程结束后做一些 ...

  3. 排错-升级Exchange 2013 CU22后程序名称显示异常

    近期在按需更新Exchange 2013 CU22补丁以便解决Microsoft Exchange Server ADV190007 Guidance for "PrivExchange&q ...

  4. [Swift]LeetCode1036.逃离大迷宫 | Escape a Large Maze

    In a 1 million by 1 million grid, the coordinates of each grid square are (x, y) with 0 <= x, y & ...

  5. 一个比Spring Boot快44倍的Java框架!

    最近栈长看到一个框架,官方号称可以比 Spring Boot 快 44 倍,居然这么牛逼,有这么神奇吗?今天带大家来认识一下. 这个框架名叫:light-4j. 官网简介:A fast, lightw ...

  6. perl学习笔记---标量

    1.perl 输出时,使用 逗号,连接多个字符串 如:print “The answer is ”,6*7, “.\n” 2.当一个字符串由双引号括起来时,如果变量前没有反斜线,则变量会被其值内插 $ ...

  7. DataIntegrityViolationException

    今天出现了这个问题: org.springframework.dao.DataIntegrityViolationException: Could not execute JDBC batch upd ...

  8. 使用Visual Studio Code开发.NET Core看这篇就够了

    作者:依乐祝 原文地址:https://www.cnblogs.com/yilezhu/p/9926078.html 在本文中,我将带着大家一步一步的通过图文的形式来演示如何在Visual Studi ...

  9. 如何用cmake编译

    本文由云+社区发表 作者:工程师小熊 CMake编译原理 CMake是一种跨平台编译工具,比make更为高级,使用起来要方便得多.CMake主要是编写CMakeLists.txt文件,然后用cmake ...

  10. 如何快速高效简洁的打开软件 干净利索的windows快捷程序启动器

    本文的主题是如何高效快捷的打开你想要打开的软件 本文介绍的应该是最简洁的一种方式,借助于windows内部的path进行设置 也可以认为是一种形式的windows应用启动器程序---win+R快速打开 ...