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