[英]JOOQ, how to deal with left outer join results when right table object is not present
db 模式包含表 AUTHOR 和 BOOK,列如下:
AUTHOR: author_id, name
BOOK: book_id, name, author_id
我使用JOOQ将数据提取到 java。
我使用 POJO 的书和作者:
public class Author { int author_id; String name; }
public class Book { int book_id; String name; }
和代码:
Result<Record> records = ctx.select()
.from(AUTHOR)
.leftOuterJoin(BOOK)
.on(AUTHOR.AUTHOR_ID.eq(BOOK.AUTHOR_ID))
.fetch();
Author author = records.get(0).into(Author.class);
Book book = records.get(0).into(Book.class);
问题是当作者没有书时, book
对象会填充默认值。 如何检测左连接导致右表没有对象? 一种方法是检查 book 主键字段是否为空。 有没有其他办法?
对象模型想要表达的内容与 SQL 能够生成的内容之间存在概念上的不匹配。 在对象模型中,人们喜欢将关系建模为嵌套集合,例如:
Author {
List<Book> books;
}
而在 RDBMS 中,人们反过来建模关系,在子实体上有外键:
CREATE TABLE book (
author_id bigint REFERENCES author(id)
)
从 SQL 生成嵌套集合(如在对象模型中)的最直接方法是使用MULTISET
运算符,如 SQL 标准中所述:
SELECT
author.*,
MULTISET(
SELECT * FROM book WHERE book.author_id = author.id
) AS books
FROM author;
不幸的是,该运算符仅在少数数据库中受支持,包括 Cubrid、Informix、Oracle,并且可以在 PostgreSQL 中进行模拟。 请注意,jOOQ 的未来版本也将支持并可能模拟它。
由于缺乏对此功能的支持,人们经常使用技巧,例如:
LEFT JOIN
运行单个查询,就像您所做的那样所有这些方法都是像 Hibernate 这样的 ORM 所采用的技巧, 每种方法都有其各自的缺点,这在这篇博文中有所记录。 ORM 并不总是做出“正确”的技巧选择(或者更确切地说:用户没有正确配置 ORM),这就是为什么他们运行大量导致性能问题的查询。
上面最好的方法之一可能是“每个实体的新查询”方法,您首先获取所有作者,然后在 2 个查询中获取每个作者的所有书籍( 不是在 N+1 个查询中! ):
SELECT * FROM author WHERE [ some predicate ]
SELECT * FROM book WHERE author_id IN (SELECT id FROM author WHERE [ some predicate ])
然后,您可以使用 jOOQ 来具体化每个结果,并使用哈希图来匹配 Java 内存中的作者和书籍。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.