JPA模块提供了事务上下文和范围,允许在事务执行的方法。
1.声明JPA模块依赖关系
添加JPA项目中模块的依赖项列表 pom.xml 文件使用此代码片段:<dependency>
<groupId>org.apache.deltaspike.modules</groupId>
<artifactId>deltaspike-jpa-module-api</artifactId>
<version>${deltaspike.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.deltaspike.modules</groupId>
<artifactId>deltaspike-jpa-module-impl</artifactId>
<version>${deltaspike.version}</version>
<scope>runtime</scope>
</dependency>
2.启用事务拦截器
您必须启用事务拦截器在项目 beans.xml文件,CDI 1.1+ and DeltaSpike v1.1.1+不需要:<beans>
<!-- Not needed with CDI 1.1+ and DeltaSpike v1.1.1+ -->
<interceptors>
<class>org.apache.deltaspike.jpa.impl.transaction.TransactionalInterceptor</class>
</interceptors>
</beans>
3.使用该模块功能
@ transactional
这个注释是可以替代ejb事务.开始使用之前,它需要实现一个CDI producer EntityManager,在注入EntityManager bean中使用 @transactional。下面的示例显示了一个简单的producer EntityManager和相应的dispose方法。
//no javaEE Server
public class EntityManagerProducer
{
//or manual bootstrapping
@PersistenceContext
private EntityManager entityManager;
@Produces
@RequestScoped
protected EntityManager createEntityManager()
{
return this.entityManager;
}
protected void closeEntityManager(@Disposes EntityManager entityManager)
{
if (entityManager.isOpen())
{
entityManager.close();
}
}
}
//EE-Server
@ApplicationScoped
public class EntityManagerProducer
{
@PersistenceUnit
private EntityManagerFactory entityManagerFactory;
@Produces
@Default
@RequestScoped
public EntityManager create()
{
return this.entityManagerFactory.createEntityManager();
}
public void dispose(@Disposes @Default EntityManager entityManager)
{
if (entityManager.isOpen())
{
entityManager.close();
}
}
}
下面的例子显示如何使用 EntityManager,@Transactional
//bean与事务方法
public class TransactionalBean
{
@Inject
private EntityManager entityManager;
@Transactional
public void executeInTransaction()
{
//...
}
}
//...
@Transactional
public class TransactionalBean
{
@Inject
private EntityManager entityManager;
//...
}
也可以通过CDI stereotypes 来使用
@Stereotype
@Transactional
@ApplicationScoped
public @interface Repository
{
}
//...
@Repository
public class TransactionalBean
{
@Inject
private EntityManager entityManager;
//...
}
下面是系统存在多个persistence-units的使用方法,使用cdi qualifiers进行配置使用.
//...
public class EntityManagerProducer
{
@PersistenceContext(unitName = "firstDB")
private EntityManager firstEntityManager;
@PersistenceContext(unitName = "secondDB")
private EntityManager secondEntityManager;
@Produces
@First
@RequestScoped
protected EntityManager createFirstEntityManager()
{
return this.firstEntityManager;
}
protected void closeFirstEntityManager(@Disposes @First EntityManager entityManager)
{
if (entityManager.isOpen())
{
entityManager.close();
}
}
@Produces
@Second
@RequestScoped
protected EntityManager createSecondEntityManager()
{
return this.secondEntityManager;
}
protected void closeSecondEntityManager(@Disposes @Second EntityManager entityManager)
{
if (entityManager.isOpen())
{
entityManager.close();
}
}
}
//...
public class FirstLevelTransactionBean
{
@Inject
private @First EntityManager firstEntityManager;
@Inject
private NestedTransactionBean nestedTransactionBean;
@Transactional
public void executeInTransaction()
{
//...
this.nestedTransactionBean.executeInTransaction();
}
}
//...
public class NestedTransactionBean
{
@Inject
private @Second EntityManager secondEntityManager;
@Transactional
public void executeInTransaction()
{
//...
}
}
下面的例子是使用指定的EntityManager
public class MultiTransactionBean
{
@Inject
private EntityManager defaultEntityManager;
@Inject
private @First EntityManager firstEntityManager;
@Inject
private @Second EntityManager secondEntityManager;
@Transactional(qualifier = Default.class)
public void executeInDefaultTransaction()
{
}
@Transactional(qualifier = First.class)
public void executeInFirstTransaction()
{
}
@Transactional(qualifier = Second.class)
public void executeInSecondTransaction()
{
}
@Transactional(qualifier = {First.class, Second.class})
public void executeInFirstAndSecondTransaction()
{
}
}
事务的嵌套使用
//...
public class FirstLevelTransactionBean
{
@Inject
private EntityManager entityManager;
@Inject
private NestedTransactionBean nestedTransactionBean;
@Transactional
public void executeInTransaction()
{
this.nestedTransactionBean.executeInTransaction();
}
}
//...
public class NestedTransactionBean
{
@Inject
private EntityManager entityManager;
@Transactional
public void executeInTransaction()
{
//...
}
}
如果FirstLevelTransactionBean和NestedTransactionBean使用的EntityManager不一样.那么在FirstLevelTransactionBean处将引发异常.
for example, to try an optional path instead of an immediate rollback.[它会尝试一个可选的路径去做,而不是立即回滚,如果可选的还不行,再回滚.我个人理解,不知道是否正确.]@TransactionScoped
略...... http://deltaspike.apache.org/documentation/jpa.html#__transactionscoped
Extended Persistence Contexts
略..... http://deltaspike.apache.org/documentation/jpa.html#_extended_persistence_contexts
JTA Support
EntityManager对象的事务管理方式有两种,分别为JTA和RESOURCE_LOCAL,即Java Transaction API方法和本地的事务管理。JPA中的事务类型通过persistence.xml文件中的“transaction-type”元素配置。例如,配置事务为JTA方式的代码如下所示。
<persistence>
<persistence-unit name="demo" transaction-type="JTA">
//其他配置省略
</persistence-unit>
</persistence>
如果使用RESOURCE_LOCAL管理事务,则配置代码如下所示。
<persistence>
<persistence-unit name="demo" transaction-type="RESOURCE_LOCAL">
//其他配置省略
</persistence-unit>
</persistence>
除了在配置文件时指明了事务的类型,不同的事务类型,不同类型的EntityManager对象,在代码中控制事务也是不同的。
By default the transaction-type used by @Transactional is RESOURCE_LOCAL. If you configure transaction-type="JTA" in the persistence.xml file, you have to enable an alternative TransactionStrategy in the beans.xml which is called org.apache.deltaspike.jpa.impl.transaction.BeanManagedUserTransactionStrategy.<beans>
<alternatives>
<class>org.apache.deltaspike.jpa.impl.transaction.BeanManagedUserTransactionStrategy</class>
</alternatives>
</beans>
If you have multiple persistence-units and you have to use both transaction-types or the settings for development have to be different than the production settings, you can use org.apache.deltaspike.jpa.impl.transaction.EnvironmentAwareTransactionStrategy instead.
In case of some versions of Weld (or OpenWebBeans in BDA mode), you have to configure it as global-alternative instead of an <alternatives> in beans.xml. That means you have to add, for example, globalAlternatives.org.apache.deltaspike.jpa.spi.transaction.TransactionStrategy =org.apache.deltaspike.jpa.impl.transaction.BeanManagedUserTransactionStrategy to /META-INF/apache-deltaspike.properties