2012-06-09 15 views
16

¿Cómo tengo el siguiente código en mi aplicación no ejb. El código funcionaUn administrador de la entidad JTA no puede usar getTransaction()

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

En una nueva aplicación que estoy usando EJB3 + JSF y me gustaría volver a utilizar la biblioteca que contiene el código de seguridad. Mi unidad de peristence para la nueva aplicación es el siguiente:

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

Mi nueva aplicación de una excepción cuando llega a esta línea:

EntityTransaction tx = em.getTransaction(); 

la excepción es:

A JTA EntityManager cannot use getTransaction() 

Lo cual es bastante claro. La pregunta es cómo voy a convertir mi código para que el contenedor administre las transacciones. Es de suponer que mis métodos de frijol deben ser anotados apropiadamente ... La pregunta es ¿cómo?

Respuesta

12

EntityTransaction se utiliza con el administrador de la entidad de tipo resource local. Si desea usar JTA, entonces tiene que usar la interfaz UserTransaction.

De la documentación: EntityTransaction - Interfaz utilizada para controlar las transacciones en los gerentes de entidades de recursos locales. El método EntityManager.getTransaction() devuelve la interfaz EntityTransaction.


Editar: Agregado pseudo código.

@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

¿cuál es la solución aquí? – rtcarlson

+0

@rtcarlson Por qué downvoted y no lo he borrado en mi publicación para usar la interfaz 'UserTransaction'. –

+0

@downvoter Si no puede explicar ni comprender, no menosprecie sin razón. –

4

En el caso más simple, simplemente funciona. Si tiene su EntityManager inyectado en EJB y no utiliza anotaciones especiales, la transacción se abrirá en el primer método EJB ingresado (esto significa que si EjbA llama a EjbB y que a su vez llama a EjbC, solo se usará una transacción en todos los métodos EJB) Si desea modificar cómo se controlan las transacciones, busque @Transaction.

La forma más sencilla de hacer una reversión es una excepción marcada con @ApplicationException (rollback = true)

puedo estar equivocado, pero a juzgar por su código que debería leer sobre la diferencia entre extendida y NORMAL EntityManager. Parece que estás utilizando un em extendido de una manera muy incómoda (mover el bucle fuera de la transacción te ayudaría a deshacerte finalmente).

Pequeño edición: si intenta utilizar UserTransaction, como el otro post sugiere, recibirá un error, porque un EntityManager estándar (que probablemente se está utilizando) utiliza el llamado CMT (contenedor operaciones gestionadas). No lo toque, a menos que entienda los tres opositions básicos (si quieres, puedo elaborar, pero francamente, no lo necesita):

  • gestionada por contenedor EntityManager EntityManager frente aplicación administrada,
  • contenedor transacciones gestionadas frente a transacciones gestionadas por aplicación,
  • EntityManager NORMAL y EntityManager EXTENDIDO.
Cuestiones relacionadas