隐式路径JOIN
适用于 ✅ 开源版 ✅ 专业版 ✅ 企业版
在 SQL 中,很多 显式 JOIN 子句仅仅是为了从给定的子表检索父表的列。例如,我们会写
-- Get all books, their authors, and their respective language SELECT a.first_name, a.last_name, b.title, l.cd AS language FROM book b JOIN author a ON b.author_id = a.id JOIN language l ON b.language_id = l.id; -- Count the number of books by author and language SELECT a.first_name, a.last_name, l.cd AS language, COUNT(*) FROM book JOIN author a ON b.author_id = a.id JOIN language l ON b.language_id = l.id GROUP BY a.id, a.first_name, a.last_name, l.cd ORDER BY a.first_name, a.last_name, l.cd
需要相当多的语法仪式(或者我们甚至可以称之为“噪音”)才能完成一个相对简单的工作。一个更简单的表示法是使用隐式连接
-- Get all books, their authors, and their respective language SELECT b.author.first_name, b.author.last_name, b.title, b.language.cd AS language FROM book b; -- Count the number of books by author and language SELECT b.author.first_name, b.author.last_name, b.language.cd AS language, COUNT(*) FROM book b GROUP BY b.author_id, b.author.first_name, b.author.last_name, b.language.cd ORDER BY b.author.first_name, b.author.last_name, b.language.cd
请注意,这种替代表示法(取决于您的喜好)可能看起来更整洁和直接,因为访问表的父表(或实体的父实体)的语义是直截了当的。
从 jOOQ 3.11 开始,此语法支持一对一关系导航,从 jOOQ 3.19 开始也支持多对一关系导航。代码生成器在生成的表上生成相关的导航方法,这些方法可以以类型安全的方式使用。导航方法名称是
- 如果子表和父表之间只有一个外键,则为父表名称(或子表名称,分别为)
- 如果子表和父表之间有多个外键,则为外键名称
可以通过使用 代码生成器策略来覆盖此默认行为。
先前查询的 jOOQ 版本如下所示
// Get all books, their authors, and their respective language create.select( BOOK.author().FIRST_NAME, BOOK.author().LAST_NAME, BOOK.TITLE, BOOK.language().CD.as("language")) .from(BOOK) .fetch(); // Count the number of books by author and language create.select( BOOK.author().FIRST_NAME, BOOK.author().LAST_NAME, BOOK.language().CD.as("language"), count()) .from(BOOK) .groupBy( BOOK.AUTHOR_ID, BOOK.author().FIRST_NAME, BOOK.author().LAST_NAME, BOOK.language().CD) .orderBy( BOOK.author().FIRST_NAME, BOOK.author().LAST_NAME, BOOK.language().CD) .fetch();
生成的 SQL 与原始 SQL 几乎相同 - 这种语法没有任何性能损失。
默认 JOIN 类型
生成的连接的默认类型是
-
对于具有非空父对象的
to-one
路径段,为INNER JOIN
-
对于具有可空父对象的
to-one
路径段,为LEFT JOIN
- 对于隐式
to-many
路径段的例外,这些路径段尚未在 FROM 子句中显式声明,否则为LEFT JOIN
(另请参阅 隐式多对路径连接了解详细信息)
可以使用 Settings.renderImplicitJoinType 或 Settings.renderImplicitJoinToManyType 来分别覆盖这些默认值,或者通过指定 显式路径连接
它是如何工作的
在 SQL 生成阶段,隐式连接路径被路径最后一个表的生成别名替换。这些路径被转换为一个连接图,该图始终 LEFT JOIN
到路径的“根表”。如果两个路径共享一个公共前缀,那么该前缀也在连接图中共享。
已知限制
- 隐式 JOIN 目前只能用于访问列,不能用于生成连接。也就是说,不可能编写像
FROM book IMPLICIT JOIN book.author
这样的内容 - 出于性能原因,隐式 JOIN 在整个 SQL 语句可用后添加到 SQL 字符串。这意味着,VisitListener SPI 实现无法观察到隐式连接的表
反馈
您对此页面有任何反馈吗? 我们很乐意倾听!