为什么 hibernate Persistence Context 在事务外不可用?
Why is the hibernate Persistence Context not available outside of a transaction?
Vlad 关于如何修复 MultipleBagsException 的示例将是我们的起点:
How to fix MultipleBagsException - Vlad Mihalcea
在其中执行 2 个后续 HQL 查询以加载 2 个延迟加载关系(包)。
在我们的项目中尝试应用它时,我注意到它仅在 2 个查询在一个事务中时才有效。所以我们必须创建一个事务来让它工作,然后很快回滚该事务。
示例:
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();
作为参考,这是一个部署到 Wildfly 20 的 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,即使我们将其设置为使用扩展上下文?
感谢@Smutje 引导我找到正确的答案。
我们案例中的解决方案是使用@Stateful 注释定义 EntityManager 的 class,根据文档,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;
}
}
Vlad 关于如何修复 MultipleBagsException 的示例将是我们的起点: How to fix MultipleBagsException - Vlad Mihalcea
在其中执行 2 个后续 HQL 查询以加载 2 个延迟加载关系(包)。
在我们的项目中尝试应用它时,我注意到它仅在 2 个查询在一个事务中时才有效。所以我们必须创建一个事务来让它工作,然后很快回滚该事务。
示例:
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();
作为参考,这是一个部署到 Wildfly 20 的 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,即使我们将其设置为使用扩展上下文?
感谢@Smutje 引导我找到正确的答案。 我们案例中的解决方案是使用@Stateful 注释定义 EntityManager 的 class,根据文档,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;
}
}