EntityManager.clear() 导致 LazyInitializationException:无法延迟初始化集合

问题描述 投票:0回答:1

我有点面临挑战,我有一个具有单向 OnetoMany 列表的实体所以我们有

Track
TrackVersions versions

的列表
Track {
    @OneToMany(mappedBy = "track", cascade = CascadeType.ALL) // lazy by default
    private final List<TrackVersion> versions = new ArrayList<>();
}

然后我有删除

TrackVersions
的服务
Track

.....

@PersistenceContext
private EntityManager entityManager;

@Transactional
public void deleteTrackVersions(Track track) {
    entityManger.flush();
    entityManger.clear();
    
    trackVerionRepo.deleteTrackVerions(track.getVersions); // This is a JPQL query that deletes track version where track version IN (? givenTrackVersions param)

   ..... some other logic

}

但是每当

trackVerionRepo.deleteTrackVerions(track.getTrackVersions)
执行它失败

failed to lazily initialize a collection of role: Track.versions, could not initialize proxy - no Session; nested exception is org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: Track.versions, could not initialize proxy - no Session

发生的事情是

entityManager.clear()
清除了持久性上下文,导致
verisons
被延迟加载被删除。所以任何连续的加载请求都会导致
LazyInitializedExcpetion

但根据我的理解,只要有一个打开的

Transaction
因此一个打开的
HibernateSession
所以没有理由发生
LazyException
,那个懒惰的集合应该再次加载!

注意:我知道 hibernate 中类似的

LazyInitilizationExcpetion
错误的帖子,但在这种情况下,我特别询问为什么它发生在
entityManager.clear()

之后
java spring hibernate jpa spring-data
1个回答
0
投票

这是由于

entityManager.clear()
电话而发生的。根据 specifications,一旦您调用
entityManager.clear()
持久性上下文中的所有托管实体都将被分离 - 主要是
Track
方法参数中接收的
deleteTrackVersions
实体。而且,正如您所说,
@OneToMany
映射默认使用延迟加载。

一旦

Track
实体变得分离,是否还有一个活跃的交易并不重要。除非您先重新附加
TrackVersion
实体,否则您将无法检索相关的
Track
实体。

要将实体重新附加到持久性上下文,您可以使用

entityManager.merge()
方法。不过,考虑到您提供的代码,我只是删除了
entityManager.clear()
电话。

作为一个无关的说明,你不能盲目相信懒加载映射配置;这是对持久性提供者的提示,但不能保证会被观察到。

© www.soinside.com 2019 - 2024. All rights reserved.