Hibernate 多对多将触发多侧选择,即使这些实体已加载 用户(m:m)书籍 类用户:: @许多 @批量大小(大小=100) 公开书目; loadAllActivateUsers() foreach用户 do(user.books)

Hibernate 多对多将触发多侧选择,即使这些实体已加载 用户(m:m)书籍 类用户:: @许多 @批量大小(大小=100) 公开书目; loadAllActivateUsers() foreach用户 do(user.books),hibernate,Hibernate,假设user1拥有书籍(1-5),user2拥有相同的书籍 调用user.books时,hibernate将触发对load book的完整查询,即使这些书籍已经加载。 Hibernate不会对这些数据什么都不做,因为实体已经在会话中,但是当book是“大实体”并且加载了大量用户时,冗余获取就会成为性能问题 我希望有一种方法来定义hibernate将触发对关联表的查询,并且如果该键已经在会话中,则不会触发对它的查询。这是意料之中的 假设我首先加载用户“John”。约翰拥有《白鲸》和《哈姆雷特》两本

假设user1拥有书籍(1-5),user2拥有相同的书籍

调用user.books时,hibernate将触发对load book的完整查询,即使这些书籍已经加载。 Hibernate不会对这些数据什么都不做,因为实体已经在会话中,但是当book是“大实体”并且加载了大量用户时,冗余获取就会成为性能问题

我希望有一种方法来定义hibernate将触发对关联表的查询,并且如果该键已经在会话中,则不会触发对它的查询。

这是意料之中的

假设我首先加载用户“John”。约翰拥有《白鲸》和《哈姆雷特》两本书。现在我加载用户“Mary”。Hibernate怎么知道Mary拥有哪本书?也许她拥有《白鲸记》,也许不是。也许她拥有哈姆雷特,也许不是。也许她还有200本书,也许没有。所以Hibernate执行一个查询来加载Mary拥有的所有书籍。如果Mary碰巧拥有一本以前加载过的书,那么内存中只会存在这本书的一个实例

如果需要,可以在单个查询中加载用户及其书籍:

user(m:m)books

class user::
    @ManyToMany
    @BatchSize(size=100)
    public List<Book> books;

loadAllActiveUsers()
foreach user
   do(user.books)

hibernate可以通过触发两步查询来了解这一点:首先从关联表加载关联id,然后加载尚未加载的关联实体。在许多多对多用例中,实体与多个所有者关联,因此有可能关联的实体已经加载。当实体具有一对多关系时,fetch join不是一个好主意。任何方式,即使是查询简单实体,也会产生1M行。
select u from User u left join fetch u.books