CDI交易管理
CDI transaction management
我正在进行从 JBoss Seam 到 CDI 的迁移项目。
以下是技术栈:
1)WildFly 8.2.0(CDI 1.2,Weld 作为 CDI 提供程序)
2)JSF 2.2
3)JPA 2
我们正在使用容器管理的 JTA 事务:
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1"
xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://xmlns.jcp.org/xml/ns/persistence
http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
<persistence-unit name="surveillenace" transaction-type="JTA">
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<jta-data-source>java:/surveillenaceDS</jta-data-source>
<!-- other configurations not shown here -->
</persistence>
并使用 @PersistenceContext
注释将 EntityManager 注入 DAO 对象。
我们正在为容器管理的事务使用 @Transaction
注释。
我的questions/Understanding在下面。
任何人都可以证实这一点,因为这对我来说是一个相对较新的领域。
1)据我了解,CDI 通过@Transaction 拦截器提供对CMT 的支持。哪个 class / 依赖项实际实现了这个拦截器?
我们需要在 pom.xml 中为此导入哪些工件?
2)由于使用了CMT,我们不需要划分任何事务,容器会管理它。我们只需要使用 EntityManager API 来持久化 Db 中的更改。
这种理解是否正确?
@Transactional
public String finishOperation() {
log.debug("in finishOperation() ") ;
try {
//operations done on managed entities
//no transaction demarcation code is required here
dao.getEntityManager.commit();
}catch(Throwable xx){
}
}
3) 考虑以下使用上述配置执行的简单场景:
Component1.somemethod()
- 在事务内部运行并保留一个实体(例如:用户)并提交事务。
在此之后,Component2 被调用如下:
Component2.somemethod()
- 在事务内部运行,但实体 User 似乎并未处于 em.contains(user)
returns false 的托管状态。
我必须再次合并此实体以使其受管理或再次从持久存储重新加载
自从 Seam 使用 conversation-scoped entity manager
以来,所有实体实例都保持在托管状态(在持久性上下文中),即使任何组件提交事务并且之后调用另一个组件也是如此。
但在 CDI 案例中,据我所知,这是由于 "transaction scoped entity manager"
而发生的。一旦事务提交,所有实体实例就会分离。
我们如何使用 CDI 实现与 Seam 相同的效果?
CDI 不提供事务管理实现作为其规范的一部分。事务管理留给程序员通过拦截器来实现,拦截器将处理所有基础知识,如开始提交等。
通常 EntityManager 存在于事务的时间跨度内。在 seam 2 中,您扩展了持久性上下文,因此它在多个请求中保持状态和附加到它的 bean。 CDI 不提供,而且由于可扩展性原因,它不建议这样做。如果你看一下 DeltaSpike,我会强烈建议在从 Seam2 迁移到 CDI 的情况下,他们提供了一个选项来延长 EntityManager 的生命周期,将其提升到对话范围,但他们也不推荐这种方法。
这里有解决您问题的 DeltaSpike 文档:
https://deltaspike.apache.org/documentation/jpa.html#ExtendedPersistenceContexts
Deltaspike 是一个很好的绑定解决方案,文档非常短,所以我会在你的情况下推荐它,此外它是由具有 seam 背景的人创建的,并提供开箱即用的事务管理。
在您使用 Java EE 7 / CDI 1.2
时回答您的问题并澄清之前仅针对 Java EE 6 / CDI 1.0 的答案
- CDI 不实现事务,但 JTA 规范实现。是的,JTA 定义了拦截器绑定
@Transactional
并且实现必须提供匹配的拦截器。由于您在 WildFly 下,您问题的答案在 JBoss JTA 实现:Narayana 中。您会找到 @Transactional(Required)
拦截器 here。其他同包。
- 是的,你的理解是正确的。
- Extended Persistence 上下文只能在 EJB 有状态会话 bean 中注入。在 Java EE 7 中,您可以尝试使用新的 JPA 2.1
Unsyncrhonized
mode(未在 CDI 中测试)。
我正在进行从 JBoss Seam 到 CDI 的迁移项目。 以下是技术栈:
1)WildFly 8.2.0(CDI 1.2,Weld 作为 CDI 提供程序)
2)JSF 2.2
3)JPA 2
我们正在使用容器管理的 JTA 事务:
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1"
xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://xmlns.jcp.org/xml/ns/persistence
http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
<persistence-unit name="surveillenace" transaction-type="JTA">
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<jta-data-source>java:/surveillenaceDS</jta-data-source>
<!-- other configurations not shown here -->
</persistence>
并使用 @PersistenceContext
注释将 EntityManager 注入 DAO 对象。
我们正在为容器管理的事务使用 @Transaction
注释。
我的questions/Understanding在下面。
任何人都可以证实这一点,因为这对我来说是一个相对较新的领域。
1)据我了解,CDI 通过@Transaction 拦截器提供对CMT 的支持。哪个 class / 依赖项实际实现了这个拦截器? 我们需要在 pom.xml 中为此导入哪些工件?
2)由于使用了CMT,我们不需要划分任何事务,容器会管理它。我们只需要使用 EntityManager API 来持久化 Db 中的更改。 这种理解是否正确?
@Transactional
public String finishOperation() {
log.debug("in finishOperation() ") ;
try {
//operations done on managed entities
//no transaction demarcation code is required here
dao.getEntityManager.commit();
}catch(Throwable xx){
}
}
3) 考虑以下使用上述配置执行的简单场景:
Component1.somemethod()
- 在事务内部运行并保留一个实体(例如:用户)并提交事务。
在此之后,Component2 被调用如下:
Component2.somemethod()
- 在事务内部运行,但实体 User 似乎并未处于 em.contains(user)
returns false 的托管状态。
我必须再次合并此实体以使其受管理或再次从持久存储重新加载
自从 Seam 使用 conversation-scoped entity manager
以来,所有实体实例都保持在托管状态(在持久性上下文中),即使任何组件提交事务并且之后调用另一个组件也是如此。
但在 CDI 案例中,据我所知,这是由于 "transaction scoped entity manager"
而发生的。一旦事务提交,所有实体实例就会分离。
我们如何使用 CDI 实现与 Seam 相同的效果?
CDI 不提供事务管理实现作为其规范的一部分。事务管理留给程序员通过拦截器来实现,拦截器将处理所有基础知识,如开始提交等。
通常 EntityManager 存在于事务的时间跨度内。在 seam 2 中,您扩展了持久性上下文,因此它在多个请求中保持状态和附加到它的 bean。 CDI 不提供,而且由于可扩展性原因,它不建议这样做。如果你看一下 DeltaSpike,我会强烈建议在从 Seam2 迁移到 CDI 的情况下,他们提供了一个选项来延长 EntityManager 的生命周期,将其提升到对话范围,但他们也不推荐这种方法。
这里有解决您问题的 DeltaSpike 文档:
https://deltaspike.apache.org/documentation/jpa.html#ExtendedPersistenceContexts
Deltaspike 是一个很好的绑定解决方案,文档非常短,所以我会在你的情况下推荐它,此外它是由具有 seam 背景的人创建的,并提供开箱即用的事务管理。
在您使用 Java EE 7 / CDI 1.2
时回答您的问题并澄清之前仅针对 Java EE 6 / CDI 1.0 的答案- CDI 不实现事务,但 JTA 规范实现。是的,JTA 定义了拦截器绑定
@Transactional
并且实现必须提供匹配的拦截器。由于您在 WildFly 下,您问题的答案在 JBoss JTA 实现:Narayana 中。您会找到@Transactional(Required)
拦截器 here。其他同包。 - 是的,你的理解是正确的。
- Extended Persistence 上下文只能在 EJB 有状态会话 bean 中注入。在 Java EE 7 中,您可以尝试使用新的 JPA 2.1
Unsyncrhonized
mode(未在 CDI 中测试)。