JTA EntityManager无法使用getTransaction()

aus*_*ser 21 java persistence ejb-3.0

如何在我的非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();
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

在一个新的应用程序中,我正在使用EJB3 + JSF,并希望重用包含上述代码的库.我对新应用程序的持久性单元如下所示:

  <persistence-unit name="myApp" transaction-type="JTA">
    <provider>org.hibernate.ejb.HibernatePersistence</provider>
    <jta-data-source>MySQLConnection</jta-data-source>
  </persistence-unit>
Run Code Online (Sandbox Code Playgroud)

我的新应用程序在遇到此行时抛出异常:

    EntityTransaction tx = em.getTransaction();
Run Code Online (Sandbox Code Playgroud)

例外是:

A JTA EntityManager cannot use getTransaction()
Run Code Online (Sandbox Code Playgroud)

这很清楚.问题是如何转换我的代码以使容器管理的事务.大概我的bean方法需要适当注释......问题是如何?

Nay*_*kar 16

EntityTransaction与资源本地类型的实体管理器一起使用.如果要使用JTA,则必须使用UserTransaction接口.

From Documentation: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 
  }
}   
Run Code Online (Sandbox Code Playgroud)

  • 那么这里的解决方案是什么? (3认同)
  • @ Emerald214为清楚起见添加了相关代码,希望这可以清除提供的解决方案。 (2认同)

fdr*_*ger 5

在最简单的情况下 - 它只是有效.如果您将EntityManager注入EJB并且不使用特殊注释,则事务将在输入的第一个EJB方法中打开(这意味着如果EjbA调用EjbB并且反过来调用EjbC,则只会在所有EJB方法中使用一个事务).如果要修改事务的控制方式,请查找@Transaction.

执行回滚的最简单方法是抛出标有@ApplicationException的异常(rollback = true)

我可能错了,但从您的代码判断,您应该阅读EXTENDED和NORMAL EntityManager之间的区别.看起来你正在以非常尴尬的方式使用扩展的em(将循环移出事务将帮助你最终摆脱).

小编辑:如果您尝试使用UserTransaction,正如另一篇文章建议的那样,您将收到错误,因为标准的EntityManager(您可能正在使用)使用所谓的CMT(容器管理事务).不要触摸它,除非你理解三个基本的选择(如果你愿意,我可以详细说明,但坦率地说,你不需要它):

  • 容器管理的EntityManager与应用程序管理的EntityManager,
  • 容器管理事务与应用程序管理事务,
  • NORMAL EntityManager和EXTENDED EntityManager.