java 清除()导致延迟初始化异常:无法延迟初始化集合

5cg8jx4n  于 2023-03-11  发布在  Java
关注(0)|答案(1)|浏览(172)

我遇到了一个挑战,我有一个单向的一对多列表的实体,所以我们有TrackTrackVersions 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()之后

0lvr5msh

0lvr5msh1#

这是由于entityManager.clear()调用而发生的。根据规范,一旦调用entityManager.clear(),持久性上下文中的所有托管实体都将被分离-主要是在deleteTrackVersions方法参数中接收的Track实体。而且,正如您所说,@OneToManyMap默认使用延迟加载。
一旦Track实体被分离,是否仍然有活动事务并不重要,除非你先重新附加Track实体,否则你将无法检索相关的TrackVersion实体。
要将一个实体重新附加到持久性上下文,可以使用entityManager.merge()方法,不过,考虑到您提供的代码,我将删除entityManager.clear()调用。
顺便说一句,您不能盲目地相信延迟/急切加载Map配置:这是对持久性提供者的一个提示,但不保证它会被遵守。

相关问题