背景 本文是 Spring Data JPA 多条件连表查询 文章的最佳实践总结。
解决什么问题? 使用 Spring Data JPA 需要针对多条件进行连表查询的场景不使用原生 SQL 或者 HQL 的时候,仅仅通过 JpaSpecificationExecutor 构造 Specification 动态条件语句来实现类型安全的多条件查询。
说明 相关上下文背景请前往 前文 了解。 这里再提一下接下来示例会用到的场景:
三个实体:作者、书、书评。其中,作者与书是一对多的关系,书与书评是一对一的关系(当然书评与读者的评价是一对多的关系,这里省去,仅用一对一来进行演示即可)。
假设有这样的后台查询条件:作者名称、书的发布时间、书评的评分。(这里每个实体取一个字段进行连表查询演示,其他字段同理)。返回书籍列表以及相关表字段。
【本文所有代码在此】
最佳实践 需要 SELECT 查询的字段,通过单独的 Java Bean 进行映射 利用 JPA 的自动实体映射结果集 @EntityGraph 注解标注返回实体需要 Fetch 的字段 无需再手动针对连表进行 fetch,解决 N+1 问题 JOIN ON 查询条件使用 join().on() 拼接 Join<Object, Object> author = root.join("author"); author.on(cb.equal(author.get("name"), param.getAuthorName())); WHERE 查询条件使用 query.where() 拼接 query.where(cb.equal(root.get("publishTime"), param.getBookPublishTime())); 代码示例 针对 Repository 需要 override 已有 findAll 方法,使用 @EntityGraph 注解 使用 @EntityGraph 注解,标注额外属性需要 fetch // BookJoinRepository....
痛点 项目中使用 Spring Data JPA 作为 ORM 框架的时候,实体映射非常方便。Spring Data Repository 的顶层抽象完全解决单实体的查询,面对单实体的复杂查询,也能使用 JpaSpecificationExecutor<T> 构造 Specification<T> 轻松应对。
而对于后台管理报表查询需求来说,需要进行连表多条件动态查询的时候,就显得无从下手。因为它并不像 MyBatis 一样能够在 XML 文件中写出动态 SQL 语句。
尽管可以使用 EntityManager 动态拼接原生 SQL 语句,但是该方法返回值为 ResultSet ,也就是说查出来的实体映射关系需要手动映射(😢这样不太优雅,已经定义出实体,还需要自己去映射)。
所以,本文的目的是,在现有实体关系的基础上,结合 Specification<T> 记录下 Spring Data JPA 多条件动态连表查询操作,以及其中的踩坑和优化。
想要直接看结论的,请看这篇 Spring Data JPA 动态多条件连表查询最佳实践。
基础操作 那么,让我们开始进入代码操作。【本文所有代码在此】
前置说明 相关依赖 Java 11 SpringBoot 2.4.2 build.gradle
plugins { id 'org.springframework.boot' version '2.4.2' id 'io.spring.dependency-management' version '1.0.11.RELEASE' id 'java' } dependencies { implementation 'org.springframework.boot:spring-boot-starter-data-jpa' compileOnly 'org.projectlombok:lombok' runtimeOnly 'mysql:mysql-connector-java' annotationProcessor 'org....
通过使用 Kotlin / Java 中 Junit5 和 Mockito 测试框架,在预约功能中演示 TDD 开发流程。
TDD 介绍 TDD(Test-Driven Development) 是一种开发流程,中文是「测试驱动开发」。用一句白话形容,就是「先写测试再开发」。先写测试除了能确保测试程式的撰写,还有一个好处:有助于在开发初期厘清程式介面如何设计。详细理论知识可以前往 Wiki 了解,这里不再过多介绍。
测试驱动开发 Test Driven Development TDD 开发流程(5步) 术语说明:
红灯 - Failure - 测试用例失败 绿灯 - Success - 测试用例成功 重构 - Refactor - 重构功能代码 具体步骤:
选定一个功能,编写测试用例 执行测试,得到【红灯】 编写满足测试用例的功能代码 再次执行,得到【绿灯】 【重构】代码 小结:
对于每一个功能,在【红灯】-【绿灯】-【重构】间来回循环往复,不断得到完善。
前置工作 代码说明 使用 Kotlin 语言(会有相对应的 Java 代码) 使用到的测试框架 Running: JUnit5 Mock: MockK / Mockito Assertion: Kotest / AssertJ 只涉及 TDD 的具体流程,不涉及单元测试如何编写(可以看 SpringBoot 单元测试各层) 功能介绍 假设一个用户预约的场景。...