javax.transaction.Transactional vs org.springframework.transaction.annotation.Transactional

152

No entiendo cuál es la diferencia real entre anotaciones javax.transaction.Transactionaly org.springframework.transaction.annotation.Transactional?

¿Es org.springframework.transaction.annotation.Transactionaluna extensión javax.transaction.Transactionalo tienen un significado totalmente diferente? ¿Cuándo deben usarse cada uno de ellos? ¿Primavera @Transactinalen la capa de servicio y Java en DAO?

Gracias por responder.

stamis
fuente

Respuestas:

125

Spring ha definido su propia anotación transaccional para hacer que los métodos Spring Bean sean transaccionales, hace años.

Java EE 7 finalmente ha hecho lo mismo y ahora permite que los métodos de bean CDI sean transaccionales, además de los métodos EJB. Entonces, desde Java EE 7, también define su propia anotación transaccional (obviamente no puede reutilizar la Spring).

En una aplicación Java EE 7, usará la anotación Java EE.

En una aplicación Spring, usará la anotación Spring.

Su uso es el mismo: informar al contenedor (Java EE o Spring) que un método es transaccional.

JB Nizet
fuente
28
Más que eso: para gobernar el universo, Spring también agregó soporte implícito para javax.transaction.Transactionalque ahora se pueda usar también en aplicaciones Spring sin ninguna acción adicional. En mi opinión, esta fue una decisión bastante mala desde el punto de vista del diseño , porque, según mi experiencia, muchos desarrolladores confunden inconscientemente a estos dos en su código, lo que lleva a problemas posteriores.
Yuriy Nakonechnyy
16
Además, org.springframework.transaction.annotation.Transactionalofrece más opciones (como readOnly, timeout) quejavax.transaction.Transactional
pierrefevrier
1
@yura, ¿qué problemas has observado?
Lee Chee Kiam
1
@LeeCheeKiam, vea dos respuestas a continuación
Yuriy Nakonechnyy
50

Otra diferencia es cómo Spring maneja las anotaciones @Transactional

  • org.springframework.transaction.annotation.Transactional siempre se tiene en cuenta
  • javax.transaction.Transactional solo se tiene en cuenta cuando hay transacciones EJB3 presentes. La presencia de transacciones EJB3 se realiza comprobando si la clase javax.ejb.TransactionAttributeestá disponible en el classpath (de la versión 2.5.3 a 3.2.5). Por lo tanto, puede terminar sin tener en cuenta sus anotaciones si solo javax.transaction.Transactionalestá en su classpath y no javax.ejb.TransactionAttribute. Este puede ser el caso si está trabajando con Hibernate: hibernate-core (4.3.7.Final) depende de jboss-transaction-api_1.2_spec (1.0.0.Final), que no proporciona javax.ejb.TransactionAttribute.
Jidehem
fuente
9
Creo que esto ya no es un problema con Spring 4.2.0: javax.transaction. La anotación transaccional también es compatible como un reemplazo
directo
no siempre se toma, si está en un método privado, por ejemplo, no se tomará.
strash
36

Tenga cuidado, (este problema ocurrió en tomcat),

Si su aplicación es la aplicación web SPRING y está utilizando el mecanismo de manejo de transacciones de Spring @org.springframework.transaction.annotation.Transactional, entonces no lo mezcle con javax.transaction.Transactional.

Eso es siempre uso, @org.springframework.transaction.annotation.Transactionalen una aplicación de primavera consistentemente.

De lo contrario, podemos terminar con este error,

org.springframework.orm.jpa.JpaSystemException: commit failed; nested exception is org.hibernate.TransactionException: commit failed

........

Caused by: java.sql.SQLException: Protocol violation: [0]
Lyju I Edwinson
fuente
1
Nota: esta respuesta es un caso especial de mi respuesta
Jidehem
3

Alcance de transacción declarativa

Tanto la @Transactionanotación Spring como la JPA le permiten definir el alcance de una transacción de aplicación determinada.

Entonces, si un método de servicio se anota con la @Transactionalanotación, se ejecutará en un contexto transaccional. Si el método de servicio utiliza múltiples DAO o repositorios, todas las operaciones de lectura y escritura se ejecutarán en la misma transacción de la base de datos.

Primavera @Transactional

La org.springframework.transaction.annotation.Transactionalanotación ha estado disponible desde la versión 1.2 del marco Spring (circa 2005), y le permite establecer las siguientes propiedades transaccionales:

  • isolation: el nivel de aislamiento de la base de datos subyacente
  • noRollbackFory noRollbackForClassName: la lista de Exceptionclases Java que se pueden activar sin activar una reversión de transacción
  • rollbackFory rollbackForClassName: la lista de Exceptionclases Java que desencadenan una reversión de transacción cuando se lanza
  • propagation: el tipo de propagación de transacción dado por PropagationEnum. Por ejemplo, si el contexto de la transacción se puede heredar (por ejemplo, REQUIRED) o se debe crear un nuevo contexto de transacción (por ejemplo, REQUIRES_NEW) o si se debe lanzar una excepción si no está presente el contexto de la transacción (por ejemplo, MANDATORY) o si se debe lanzar una excepción si se encuentra un contexto de transacción actual (por ejemplo, NOT_SUPPORTED).
  • readOnly: si la transacción actual solo debería leer datos sin aplicar ningún cambio.
  • timeout: cuántos segundos se debe permitir que se ejecute el contexto de la transacción hasta que se produzca una excepción de tiempo de espera.
  • valueo transactionManager: el nombre del TransactionManagerbean Spring que se utilizará al vincular el contexto de la transacción.

Java EE @Transactional

La javax.transaction.Transactionalanotación fue agregada por la especificación Java EE 7 (circa 2013). Entonces, la anotación Java EE se agregó 8 años después que su contraparte de Spring.

Java EE @Transactionaldefine solo 3 atributos:

  • dontRollbackOn: la lista de Exceptionclases Java que se pueden activar sin activar una reversión de transacción
  • rollbackOn: la lista de Exceptionclases Java que desencadenan una reversión de transacción cuando se lanza
  • value: la estrategia de propagación, dada por la TxTypeEnum. Por ejemplo, si el contexto de la transacción se puede heredar (por ejemplo, REQUIRED) o se debe crear un nuevo contexto de transacción (por ejemplo, REQUIRES_NEW) o si se debe lanzar una excepción si no está presente el contexto de la transacción (por ejemplo, MANDATORY) o si se debe lanzar una excepción si se encuentra un contexto de transacción actual (por ejemplo, NOT_SUPPORTED).

¿Cuál elegir?

Si está usando Spring o Spring Boot, use la @Transactionalanotación Spring , ya que le permite configurar más atributos que la @Transactionalanotación Java EE .

Si usa Java EE solo y despliega su aplicación en un servidor de aplicaciones Java EE, use la anotación Java EE `` @ Transactional`.

Para obtener más detalles sobre cómo la configuración del nivel de aislamiento es diferente cuando se utilizan las @Transactionaldefiniciones Spring o Java EE , consulte este artículo .

Vlad Mihalcea
fuente