web-dev-qa-db-ja.com

JTA EntityManagerはgetTransaction()を使用できません

非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メソッドには適切に注釈を付ける必要があります...質問はどのようにですか?

21
auser

EntityTransactionは、タイプlocalのエンティティマネージャーで使用されます。 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 
  }
}   
15
Nayan Wadekar

最も単純なケースでは-それはちょうど動作します。 EntityManagerをEJBに注入し、特別な注釈を使用しない場合、トランザクションは最初に入力されたEJBメソッドで開きます(つまり、EjbAがEjbBを呼び出し、それがEjbCを呼び出す場合、すべてのEJBメソッドで1つのトランザクションのみが使用されます)。トランザクションの制御方法を変更する場合は、@ Transactionを検索します。

ロールバックを行う最も簡単な方法は、@ ApplicationException(rollback = true)でマークされた例外をスローすることです

私は間違っているかもしれませんが、あなたのコードから判断すると、EXTENDEDとNORMAL EntityManagerの違いを読む必要があります。拡張emを非常に厄介な方法で使用しているように見えます(ループをトランザクションから外すと、最終的に取り除くのに役立ちます)。

小さな編集: UserTransactionを使用しようとすると、他の投稿が示唆するように、エラーが発生します。標準のEntityManager(おそらく使用している)はいわゆるCMT(Container Managed Transactions)を使用するためです。あなたが3つの基本的なポジションを理解しない限り、それに触れないでください(あなたが望むなら、私は詳しく説明できますが、率直に言って、あなたはそれを必要としません):

  • コンテナ管理のEntityManagerとアプリケーション管理のEntityManager、
  • コンテナ管理トランザクションとアプリケーション管理トランザクション、
  • NORMAL EntityManagerおよびEXTENDED EntityManager。
5
fdreger

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

serTransactionとEntityManagerはどのように相互作用しますか?

1
David Abragimov