如何在非ejb应用程序中使用以下代码。代码有效。
@Override
public void saveItems(Collection<T> items) {
synchronized (em) {
EntityTransaction tx = em.getTransaction();
try {
tx.begin();
for (T item : items) {
saveItem_((Class<T>) null, item);
}
tx.commit();
} finally {
if (tx.isActive()) {
tx.rollback();
}
}
}
}
在新的应用程序中,我正在使用EJB3 + JSF,并希望重用包含上述代码的库。我对新应用程序的持久性单元如下所示:
<persistence-unit name="myApp" transaction-type="JTA">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<jta-data-source>MySQLConnection</jta-data-source>
</persistence-unit>
我的新应用程序在遇到此行时抛出异常:
EntityTransaction tx = em.getTransaction();
例外是:
A JTA EntityManager cannot use getTransaction()
哪个足够清楚。问题是如何转换我的代码以使容器管理的事务。大概我的bean方法需要适当注释......问题是如何?
答案 0 :(得分:15)
EntityTransaction
与资源本地类型的实体管理器一起使用。如果要使用JTA,则必须使用UserTransaction
接口。
来自文档: EntityTransaction - 用于控制资源本地实体管理器上的事务的接口。 EntityManager.getTransaction()方法返回EntityTransaction接口。
修改:添加了伪代码。
@Resource
private SessionContext sessionContext;
void execute(){
UserTransaction userTxn = sessionContext.getUserTransaction();
try{
userTxn.begin();
/**
* do-something
*/
userTxn.commit();
} catch(Throwable e){
userTxn.rollback(); //-- Include this in try-catch
}
}
答案 1 :(得分:5)
在最简单的情况下 - 它只是起作用。如果您将EntityManager注入EJB并且不使用特殊注释,则事务将在输入的第一个EJB方法中打开(这意味着如果EjbA调用EjbB并且反过来调用EjbC,则只会在所有EJB方法中使用一个事务)。如果要修改事务的控制方式,请查找@Transaction。
执行回滚的最简单方法是抛出标有@ApplicationException的异常(rollback = true)
我可能错了,但从您的代码判断,您应该阅读EXTENDED和NORMAL EntityManager之间的区别。看起来你正在以一种非常尴尬的方式使用扩展的em(将循环移出事务将帮助你最终摆脱)。
小编辑:如果您尝试使用UserTransaction,正如其他帖子建议的那样,您将收到错误,因为标准的EntityManager(您可能正在使用)使用所谓的CMT(Container)托管交易)。不要触摸它,除非你理解三个基本的选择(如果你愿意,我可以详细说明,但坦率地说,你不需要它):
答案 2 :(得分:1)
“可以为某人节省时间。”
它确实节省了我的时间!我希望我几天前就找到了你的解决方案。我一直在努力研究如何在 JTA 持久性单元的上下文中处理 bean 管理的事务。我们的大部分使用只是一个 bean 方法中的一个 JPA DML 调用。问题是在执行单个 DML 操作后,对存储过程的后续调用(在同一 bean 方法中)将失败,抱怨无法在正在运行的事务中启动另一个事务。文档很全面但很繁琐。
这是关键:@Resource UserTransaction utx;
谢谢!
答案 3 :(得分:0)
仅总结适用于Jboss EAP6和Hibernate 4.2.18.Final的代码。
可以为某人节省时间。
persistence.xml
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
version="2.0">
<persistence-unit name="myApp" transaction-type="JTA">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<jta-data-source>jdbc/MySQLConnection</jta-data-source>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5Dialect"/>
<property name="hibernate.transaction.manager_lookup_class" value="org.hibernate.transaction.JBossTransactionManagerLookup"/>
<!--
<property name="hibernate.show_sql" value="true" />
-->
</properties>
</persistence-unit>
java
import javax.annotation.Resource;
import javax.persistence.EntityManager;
import javax.transaction.UserTransaction;
public class MyClass {
@PersistenceContext(unitName = "myApp")
protected EntityManager em;
@Resource
UserTransaction utx;
public void execute(..) throws Exception {
try {
utx.begin();
em.remove(..);
em.merge(..);
em.persist(..);
utx.commit();
} catch (Exception ex) {
try {
utx.rollback();
} catch (Exception re) {
throw new RollbackFailureException("An error occurred attempting to roll back the transaction.", re);
}
throw ex;
}
}
}
pom.xml
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>${hibernate.version}</version>
<scope>provided</scope>
</dependency>
链接:
应用程序管理的实体管理器https://docs.oracle.com/cd/E19798-01/821-1841/bnbra/index.html
How does the UserTransaction and the EntityManager interact?