2010-03-25 15 views
26

¿Alguien puede explicar qué se diferencia entre:¿Cuál es la diferencia entre @Resource UserTransaction y EntityManager.getTransaction()

@Resource 
UserTransaction objUserTransaction; 

y

EntityManager.getTransaction(); 

Y transacción también lo es administrado contenedor? y cómo debería hacerlo en la fachada de mi sesión si quiero insertar tres filas en la tabla de transacción.

+1

Un buen artículo para tener una mejor idea acerca de Transacciones EJB, IMO, una lectura obligada http://entjavastuff.blogspot.com/2011/02/ejb-transaction-management-going-deeper.html – thirdy

Respuesta

26

EJB son componentes transaccionales. La transacción puede ser gestionada por el propio servidor de aplicación (CMT - transacción gestionada por contenedor), o manualmente por usted mismo dentro del EJB (BMT - transacción gestionada por bean).

EJB admite transacciones distribuidas a través de la especificación JTA. La transacción distribuida se controla utilizando UserTransaction, que tiene los métodos begin, commit, rollback.

Con CMT, el servidor de aplicaciones inicia, compromete y retrotrae la transacción (según el transaction annotations) para usted y no puede interferir. Esto significa que no debe acceder al UserTransaction en este caso. Sin embargo, con BMT, usted hace eso manualmente y usted mismo controla la transacción usando el UserTransaction.

Pasemos ahora al EntityManager. Una implementación de JPA se puede usar dentro de un servidor de aplicaciones o independiente. Si se usa en forma independiente, debe usar EntityManage.getTransaction para delimitar la transacción JDBC usted mismo. Si se usa dentro de un servidor de aplicaciones, el EntityManager cooperó con el administrador de transacciones distribuido JTA de forma transparente para usted.

La mayoría de las veces, utiliza CMT con la anotación @Required en el EJB. Esto significa que no necesita acceder ni al UserTransaction ni al EntityManager.getTransaction. La aplicación. el servidor inicia y confirma la transacción, pero también se encarga de deshacer si se produce una excepción. Esto es lo que recomendaría para su fachada.

(hay más sutilezas, como el PersistenceContextType o el alistamiento Manual del gestor de la entidad en una transacción distribuida con EntityManager.joinTransaction, pero eso es sólo si utiliza las tecnologías de diferentes maneras como el valor por defecto).

+3

¿Estás seguro de que 'EntityManager # getTransaction()' coopera con la transacción distribuida JTA cuando se ejecuta dentro de un servidor de aplicaciones? No creo que lo haga, lo que entiendo es que devuelve una transacción local de recursos que se puede usar para conservar los datos * fuera de la transacción JTA actual. –

+0

@Pascal El 'EntityManager' coopera con JTA, por lo que no debe usar' EntityManager # getTransaction' en absoluto. Según el javadoc, 'EntityManager # getTransaction' arroja' IllegalStateException' si se invoca en un JTA EntityManager. – ewernli

+2

De hecho, 'getTransaction' arroja una excepción cuando se invoca en un JTA EntityManager). En realidad, el ejemplo que tenía en mente (de "Pro JPA 2") es obtener un EM administrado por aplicaciones y local de recursos en un Session Bean, p. Ej. para el registro de auditoría, y una transacción local de recursos que puede comenzar/comprometer tantas veces como desee fuera de la transacción JTA. Pero me doy cuenta de que leí mal tu respuesta, esto es diferente de lo que escribiste. ¡Gracias! –

7

UserTransaction refiere a la entidad transacción JTA. Solo podrá usar esto cuando haya un módulo JTA disponible en el servidor de aplicaciones: por ejemplo, si está implementando una aplicación con esto en Tomcat (que de manera predeterminada no admite JTA), el código que depende de esto fallará . Este es el tipo predeterminado de transacción utilizado en EJB y MDB.

EntityManager.getTransaction() recupera local entidad de transacción. Esto también a veces se conoce como una transacción local de recursos.

Las transacciones locales de recursos son muy diferentes de las transacciones JTA: entre otras cosas, las transacciones locales de recursos son específicas de un recurso, mientras que las transacciones JTA tienden a ser específicas de un hilo en particular.

Para obtener más información sobre la diferencia entre los recursos transacciones locales y JTA, vea este Stackoverflow respuesta aquí: What is the difference between a JTA and a local transaction?

0

Además de @ respuesta de Marco, que hace bien en decir la diferencia entre la JTA y sus recursos transacciones locales.

Las transacciones gestionadas en el contenedor son [como se denominan] administradas por el contenedor en lugar de su aplicación. Esto se hace a través del nivel EJB donde solo necesita escribir su método y el contenedor ajustará el método en un contexto de transacción, de modo que si alguna parte de su método o sus llamadas de nivel inferior lanza una excepción, la transacción se revertirá.

También se puede ajustar con anotaciones. Más información se puede encontrar aquí https://docs.oracle.com/javaee/5/tutorial/doc/bncij.html

Tenga en cuenta que esto solo se realiza a través de EJB, y los administradores de entidades que se inyectan en el nivel web (por ejemplo, servlets o API REST) ​​no se gestionan por el contenedor, en cuyo caso debe busque la transacción usando @Resource UserTransaction o EntityManager.getTransaction, begin() y commit() usted mismo.

Desde Java EE 6 tiene permitido tener EJB dentro del nivel web, por lo que no necesita tener un diseño de proyecto excesivamente complejo a menos que empiece a querer exponer sus EJB como servicios web.

+0

En EE, las transacciones gestionadas en contenedor están disponibles fuera de EJB mediante la anotación "@Transactional". –

+0

Las transacciones JTA son * no * necesariamente CMT, ya que JTA se puede usar fuera de los servidores de aplicaciones (o "contenedores") con bibliotecas como Bitronix y Atomikos. – Marco

Cuestiones relacionadas