java—为什么hibernate持久性上下文在事务外部不可用?

jqjz2hbq  于 2021-07-08  发布在  Java
关注(0)|答案(1)|浏览(294)

vlad关于如何修复multiplebagsexception的例子将是我们的出发点:how to fix multiplebagsexception-vlad mihalcea
在其中,它执行两个后续的hql查询,以便加载2个延迟加载关系(bags)。
在我们的项目中尝试应用这个方法时,我注意到只有当两个查询在一个事务中时,它才起作用。因此,我们必须创建一个事务以使其正常工作,然后很快回滚所述事务。
例子:

utx.begin();
List<Post> posts = entityManager.createQuery("""
    select distinct p
    from Post p
    left join fetch p.comments
    where p.id between :minId and :maxId""", Post.class)
.setParameter("minId", 1L)
.setParameter("maxId", 50L)
.setHint(QueryHints.PASS_DISTINCT_THROUGH, false)
.getResultList();

posts = entityManager.createQuery("""
    select distinct p
    from Post p
    left join fetch p.tags t
    where p in :posts""", Post.class)
.setParameter("posts", posts)
.setHint(QueryHints.PASS_DISTINCT_THROUGH, false)
.getResultList();
utx.rollback();

作为参考,这是一个部署到wildfly20的javaee项目(不是spring)。persistence.xml中定义了持久性单元

<persistence-unit name="some-p-unit-name">
    <jta-data-source>java:/jdbc/someDB</jta-data-source>
</persistence-unit>

entitymanager的定义如下:

@PersistenceContext(type = PersistenceContextType.EXTENDED, unitName = "some-p-unit-name")
private EntityManager em;

@Produces
@RequestScoped
@SomeResource // this is an annotation to differentiate it from another entity manager that can also be injectable
public EntityManager getEm() {
    return em;
}

那么,为什么我们需要启动一个事务来启用persistencecontext,即使我们将它设置为使用扩展上下文?

0ve6wy6x

0ve6wy6x1#

谢谢@smutje让我找到了正确的答案。本例中的解决方案是用@stateful注解定义entitymanager的类,根据文档,persistencecontext仅适用于容器管理场景中的有状态ejb。
下面是示例代码。请注意有状态注解和持久性上下文类型=extended。

@Stateful
public class Resources {
    @PersistenceContext(type = PersistenceContextType.EXTENDED, unitName = "some-p-unit-name")
    private EntityManager em;

    @Produces
    @RequestScoped
    public EntityManager getEm() {
        return em;
    }
}

相关问题