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主键字段是否为空。还有其他办法吗?
答案 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 PostgreSQL。 Note 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内存中的作者和书籍。