我遇到了一个挑战,我有一个单向的一对多列表的实体,所以我们有Track
和TrackVersions versions
列表
Track {
@OneToMany(mappedBy = "track", cascade = CascadeType.ALL) // lazy by default
private final List<TrackVersion> versions = new ArrayList<>();
}
然后,我有一个按Track
删除TrackVersions
的服务
.....
@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
,该惰性收集应该已经被再次加载!
注意:我知道类似的关于LazyInitilizationExcpetion
错误的帖子,但是在这个例子中,我特别想知道为什么它发生在entityManager.clear()
之后
1条答案
按热度按时间0lvr5msh1#
这是由于
entityManager.clear()
调用而发生的。根据规范,一旦调用entityManager.clear()
,持久性上下文中的所有托管实体都将被分离-主要是在deleteTrackVersions
方法参数中接收的Track
实体。而且,正如您所说,@OneToMany
Map默认使用延迟加载。一旦
Track
实体被分离,是否仍然有活动事务并不重要,除非你先重新附加Track
实体,否则你将无法检索相关的TrackVersion
实体。要将一个实体重新附加到持久性上下文,可以使用
entityManager.merge()
方法,不过,考虑到您提供的代码,我将删除entityManager.clear()
调用。顺便说一句,您不能盲目地相信延迟/急切加载Map配置:这是对持久性提供者的一个提示,但不保证它会被遵守。