2012-06-09 13 views
16

Wie habe ich den folgenden Code in meiner Nicht-EJB-Anwendung. Der Code funktioniert.Ein JTA EntityManager kann getTransaction() nicht verwenden

@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(); 
      } 
     } 
    } 
} 

In einer neuen Anwendung verwende ich EJB3 + JSF und möchte die Bibliothek erneut verwenden Sie den Code oben enthält. Meine peristence Einheit für die neue Anwendung sieht wie folgt aus:

<persistence-unit name="myApp" transaction-type="JTA"> 
    <provider>org.hibernate.ejb.HibernatePersistence</provider> 
    <jta-data-source>MySQLConnection</jta-data-source> 
    </persistence-unit> 

Meine neue Anwendung eine Ausnahme aus, wenn es diese Zeile hits:

EntityTransaction tx = em.getTransaction(); 

die Ausnahme ist:

A JTA EntityManager cannot use getTransaction() 

Welche ist klar genug. Die Frage ist, wie ich meinen Code konvertieren würde, damit die Transaktionen vom Container verwaltet werden. Vermutlich müssen meine Bohnenmethoden angemessen kommentiert werden ... Die Frage ist wie?

Antwort

12

EntityTransaction wird mit Entitätsmanager vom Typ Ressource lokal verwendet. Wenn Sie JTA verwenden möchten, müssen Sie die Schnittstelle UserTransaction verwenden.

Von der Dokumentation: EntityTransaction - Schnittstelle zum Steuern von Transaktionen auf Ressourcen-lokalen Entity Managern. Die EntityManager.getTransaction() -Methode gibt die EntityTransaction-Schnittstelle zurück.


Edit: Added Pseudo-Code.

@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 
    } 
} 
+3

Also was ist die Lösung hier? – rtcarlson

+0

@rtcarlson Warum heruntergeregelt & habe ich nicht in meiner Post gelöscht, um 'UserTransaction' Schnittstelle zu verwenden. –

+0

@ downvoter Wenn Sie nicht erklären und verstehen können, nicht ohne Grund abmelden. –

4

Im einfachsten Fall - es funktioniert einfach. Wenn Sie Ihren EntityManager in EJB einfügen und keine speziellen Anmerkungen verwenden, wird die Transaktion in der ersten eingegebenen EJB-Methode geöffnet (dh wenn EjbA EjbB aufruft und diese EjbC aufruft, wird nur eine Transaktion für alle EJB-Methoden verwendet)). Wenn Sie ändern möchten, wie Transaktionen gesteuert werden, suchen Sie nach @Transaction.

Der einfachste Weg, ein Rollback zu tun ist, eine Ausnahme mit @ApplicationException markiert zu werfen (Rollback = true)

ich falsch sein kann, aber aus dem Code zu urteilen Sie auf der Differenz zwischen EXTENDED und NORMAL lesen sollen EntityManager. Es sieht so aus, als ob Sie ein Extended Em auf sehr peinliche Weise benutzen (das Verschieben der Schleife aus der Transaktion würde Ihnen helfen, endlich loszuwerden).

Kleine edit: wenn Sie versuchen, Usertransaction zu verwenden, da die anderen Post schon sagt, wird eine Fehlermeldung angezeigt, weil ein Standard-EntityManager (die Sie wahrscheinlich verwenden) nutzt das sogenannte CMT (Container Managed Transaktionen). Berühren Sie es nicht, wenn Sie die drei grundlegenden opositions verstehen (wenn Sie möchten, kann ich erarbeiten, aber ehrlich gesagt, Sie werden es nicht brauchen):

  • Container verwaltet EntityManager im Vergleich Anwendung EntityManager verwaltet,
  • Behälter verwaltete Transaktionen versus anwendungsverwaltete Transaktionen,
  • NORMAL EntityManager und EXTENDED EntityManager.
Verwandte Themen