AbstractPersistentCollection

AbstractPersistentCollection

我想与我的数据库的所有用户一起显示一个表。该表还应包含用户对象中包含的列表的元素数。
因为我只需要大小/数量,所以我想防止获取整个列表。因此,我正在使用LazyCollectionOption.EXTRA,文档说明:

EXTRA = .size()和.contains()不会初始化整个集合

但是以下内容仍然无效:

@Entity
class User {
    @OneToMany
    @LazyCollection(LazyCollectionOption.EXTRA)
    List<Transaction> transactions;
}

当我调用user.getTransactions().size()时,结果是:

引起原因:org.hibernate.LazyInitializationException:无法懒惰
初始化角色集合:User.transactions,无法
初始化代理-没有会话
org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:575)

org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:214)

org.hibernate.collection.internal.AbstractPersistentCollection.readSize(AbstractPersistentCollection.java:155)

org.hibernate.collection.internal.PersistentBag.size(PersistentBag.java:278)

最佳答案

即使@LazyCollection(LazyCollectionOption.EXTRA)并不是引起您麻烦的原因,但如果您关心应用程序性能,也可以使用you shouldn't be using EXTRA lazy fetching anyway

我认为您正在获取一个Hibernate Session中的Users列表,该列表在您要访问User的事务之前已关闭。

这是LazyInitializationException的典型情况,因为在仍打开Session时尚未初始化嵌套集合。

获取所有用户及其所有交易将使您得到笛卡尔积,这会导致性能问题。

我认为可以获取“用户”列表,并使用子选择访存来检索事务:

@OneToMany
@Fetch(FetchMode.SUBSELECT)
List<Transaction> transactions;

这将发出更多选择,以便在需要时提取所有未初始化的事务。这将要求您访问至少一个当前附加的用户事务,以触发对所有未初始化的当前附加的事务的附加获取。

否则,您可以使用批量获取:
@OneToMany
@BatchSize(size = 50)
List<Transaction> transactions;

同样,这需要一个打开的会话,并且在请求某个User.transactions时,所有与用户相关的交易将以50个为一批进行初始化。

但是,由于@BatchSize仅设置为集合,而不是@Entity级别,这意味着在最佳情况下,您仍将需要N个附加查询来查询N个当前附加的Users。如果每个用户有50多个事务,则您将需要N个以上的查询。这可能比仅需要一个查询(the original query is rerun using a sub-select to fetch all query related Users' transactions)的子选择获取要差。

10-04 13:15