繁体   English   中英

JOOQ,当右表对象不存在时如何处理左外连接结果

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM