@Transactional
先引用下原文档:
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 calledorg.apache.deltaspike.jpa.impl.transaction.BeanManagedUserTransactionStrategy
.
<beans>
<alternatives>
<class>org.apache.deltaspike.jpa.impl.transaction.BeanManagedUserTransactionStrategy</class>
</alternatives>
</beans>
意思是默认事务类型是 RESOURCE_LOCAL 的 如果你要用 JTA 的话要在 beans 上加入上面代码, 但我加了,报错 “A JTA EntityManager cannot use getTransaction()”
看文档,下面还有一行小字:
In case of some versions of Weld (or OpenWebBeans in BDA mode), you have to configure it as a global alternative instead of an alternative
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
.
说有一些版本的服务器要加上一个 apache-deltaspike.properties 并加一条设置。按文档加之,成功,我在Wildfly 8.2.1 和 9.0.2 上都试过了,都需要加。
TransactionStrategy 的选择:
以下内容部分基于我的理解,没有完全测试,如有问题欢迎指正。
根据文档有以下几个可选:
org.apache.deltaspike.jpa.impl.transaction.ResourceLocalTransactionStrategy
org.apache.deltaspike.jpa.impl.transaction.BeanManagedUserTransactionStrategy
org.apache.deltaspike.jpa.impl.transaction.ContainerManagedTransactionStrategy
org.apache.deltaspike.jpa.impl.transaction.EnvironmentAwareTransactionStrategy
第一个是默认值,那怎么选呢?
要先说说得到 EntityManager 的两种方式:
@PersistenceContext
private EntityManager entityManager;
@PersistenceUnit
private EntityManagerFactory entityManagerFactory;
@Produces
@Default
@RequestScoped
public EntityManager create()
{
return this.entityManagerFactory.createEntityManager();
}
官方文档说在非EE服务器中用第一种, 而在EE服务器中用第二种,
这两者的区别应该是第一种是包含一些事务设置的EntityManager,而第二种是不包括事务设置的
如果要用第一种方式那会使用EE容器的JTA事务,会使用persistence.xml中的一些事务设置,例如:
<property name="transaction.factory_class" value="org.hibernate.transaction.JTATransactionFactory"/> <property name="hibernate.transaction.manager_lookup_class" value="org.hibernate.transaction.JBossTransactionManagerLookup"/> <property name="hibernate.connection.autocommit" value="false"/> <property name="hibernate.current_session_context_class" value="jta"/>
而用用第二种,就不会使用,而且设置了还有可能会出错,我就遇到了:"no transaction is in progress"
下面开始说选哪个:
1. RESOURCE_LOCAL
这个几乎不用设置:因为默认就是它,org.apache.deltaspike.jpa.impl.transaction.ResourceLocalTransactionStrategy, 根据情况选EntityManager的注入方式就好。
2.JTA
这个情况就多了,
(1).@PersistenceUnit 得到的 EntityManager
org.apache.deltaspike.jpa.impl.transaction.BeanManagedUserTransactionStrategy
(2). @PersistenceContext
得到的 EntityManager
org.apache.deltaspike.jpa.impl.transaction.ContainerManagedTransactionStrategy
3.多个数据源两种事务类型混用(这种奇葩的方式,实在想不出啥时候会有这种情况发生!)
org.apache.deltaspike.jpa.impl.transaction.EnvironmentAwareTransactionStrategy