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

时间:2015-10-07 13:43:39

标签: java orm jooq

db模式包含表AUTHOR和BOOK,其中的列如下所示:

AUTHOR: author_id, name
BOOK: book_id, name, author_id

我使用JOOQ将数据提取到java。

我使用POJO Book and Author:

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主键字段是否为空。还有其他办法吗?

1 个答案:

答案 0 :(得分:2)

对象模型想要表达的内容与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和it can be emulated in PostgreSQLNote that future versions of jOOQ will also support, and possibly emulate it

缺乏对此功能的支持,人们常常使用技巧,例如:

  • 延迟加载
  • 按实体运行新查询
  • 使用LEFT JOIN以您的方式运行单个查询

所有这些方法都是像Hibernate,each with their individual drawback, which is documented in this blog post这样的ORM使用的技巧。 ORM并不总是做出正确的&#34;选择技巧(或者更确切地说:用户不能正确配置ORM),这就是他们运行大量查询导致性能问题的原因。

上述最好的方法之一可能是每个实体的新查询&#34;方法,首先获取所有作者,然后在2个查询(not in N+1 queries!)中为每位作者提供所有书籍:

SELECT * FROM author WHERE [ some predicate ]
SELECT * FROM book WHERE author_id IN (SELECT id FROM author WHERE [ some predicate ])

然后,您可以使用jOOQ实现每个结果,并使用散列图匹配Java内存中的作者和书籍。