编程语言
首页 > 编程语言> > java – 带有Spring代理的LazyCollectionOption.EXTRA?

java – 带有Spring代理的LazyCollectionOption.EXTRA?

作者:互联网

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

EXTRA = .size() and .contains() won’t initialize the whole collection

但以下情况仍无效:

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

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

Caused by: org.hibernate.LazyInitializationException: failed to lazily
initialize a collection of role: User.transactions, could not
initialize proxy – no Session at
org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:575)
at
org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:214)
at
org.hibernate.collection.internal.AbstractPersistentCollection.readSize(AbstractPersistentCollection.java:155)
at
org.hibernate.collection.internal.PersistentBag.size(PersistentBag.java:278)

解决方法:

我不认为这是:

@LazyCollection(LazyCollectionOption.EXTRA)

这会给你带来麻烦.

我认为您正在获取Hibernate会话中的“用户”列表,该列表在您想要访问用户的事务之前关闭.

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

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

我认为获得用户列表很好,并使用子选择提取来检索事务:

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

这将再发出一个select以在需要时获取所有未初始化的事务.这将要求您访问至少一个当前附加的用户事务,以触发所有未初始化的当前附加事务的额外提取.

否则您可以使用批量提取:

@OneToMany
@BatchSize(size = 50)
List<Transaction> transactions;

同样,这需要一个打开的会话,并且在请求某个User.transactions时,所有用户关联的事务将以50个批次进行初始化.

但由于@BatchSize仅为集合设置,而不是@Entity级别,这意味着在最好的情况下,您仍然需要N个额外查询N当前连接的用户.如果每个用户有超过50个交易,您将需要超过N个查询.这可能比子选择提取更糟糕,这只需要一个查询(the original query is rerun using a sub-select to fetch all query related Users’ transactions).

标签:java,spring,jpa,hibernate,hibernate-mapping
来源: https://codeday.me/bug/20190830/1770684.html