Este artículo realizará una investigación en profundidad sobre la gestión de transacciones de Spring. Principalmente presenta cómo funciona @Transactional en la parte inferior. El siguiente artículo presentará:
Uso de atributos tales como propagación (propagación de transacciones) y aislamiento (aislamiento)
¿Cuáles son las trampas del uso de transacciones y cómo evitarlo?
JPA y gestión de transacciones
Es importante que JPA en sí no proporcione ningún tipo de gestión de transacciones declarativas. Si usa JPA fuera de un contenedor de inyección de dependencia, el desarrollador debe implementar mediante programación la transacción.
UserTransaction utx = entityManager.getTransaction (); try {utx.begin (); BusinessLogic (); utx.ComMit ();} Catch (Exception ex) {utx.rollback (); throwex;}Esta forma de gestión de transacciones permite que el alcance de la transacción se exprese claramente en el código, pero tiene las siguientes desventajas:
El código repetido y los errores son propensos a
Cualquier error puede tener un mayor impacto
Los errores son difíciles de depurar y reproducir
Reduce la legibilidad de la base de código
¿Qué pasa si el método llama a otros métodos de transacción?
Usando Spring @Transactional
Usando Spring @Transactional, el código anterior se simplifica para:
@Transactional PublicVoid BusinessLogic () {... use Entity Manager dentro de una transacción ...}El código es más conciso y legible, y también es la forma recomendada de tratar en la primavera en la actualidad.
Muchos aspectos importantes, como la propagación de transacciones, se pueden manejar automáticamente utilizando @Transactional. En este caso, si BusinessLogic () llama a otro método de transacción, el método determinará cómo unirse a la transacción en ejecución en función de las opciones.
Un posible inconveniente de este poderoso mecanismo es que oculta la operación subyacente y es difícil de depurar cuando no funciona correctamente.
@Significado transaccional
Uno de los puntos clave sobre @Transactional es considerar dos conceptos separados, los cuales tienen su propio alcance y ciclo de vida:
Contexto de persistencia (contexto de persistencia)
transacción de base de datos
@Transactional mismo define el alcance de una sola transacción. Esta transacción está dentro del alcance del contexto de persistencia.
El contexto de persistencia en JPA es EntityManager, y la implementación interna utiliza la sesión de Hibernate (usando Hibernate como proveedor de persistencia).
El contexto de persistencia es solo un objeto sincrónico que registra el estado de los objetos Java de una colección finita y asegura que los cambios en estos objetos finalmente persistan en la base de datos.
Este es un concepto muy diferente de una sola transacción. Se puede usar un administrador de entidades en múltiples transacciones, y de hecho se usa de esta manera.
¿Cuándo abarca EntityManager múltiples transacciones?
La situación más común es cuando una aplicación usa la sesión abierta en modo View para manejar las excepciones de inicialización perezosa. Los artículos anteriores han introducido las ventajas y desventajas de este enfoque.
En este caso, las consultas múltiples administradas por la capa de vista se encuentran en transacciones separadas, en lugar de una lógica comercial de transacciones individuales, pero estas consultas son administradas por el mismo gerente de entidad.
Otro escenario es que el desarrollador marca el contexto de persistencia como persistenceContextType.Extended, lo que significa que puede responder a múltiples solicitudes.
¿Cómo definir la relación entre EntityManager y la transacción?
Esto es elegido por los desarrolladores de aplicaciones, pero la forma más común para JPA Entity Manager es el modo "Entity Manager por transacción de aplicación". Los métodos comunes de la inyección del administrador de entidades son:
@PersistenceContext PrivateEntityManager EM;
El valor predeterminado es el modo "Entity Manager por transacción". En este modo, si el Administrador de entidades se usa dentro del método @Transactional, el método se ejecutará en una sola transacción.
¿Cómo funciona @PersistenCeContext?
La pregunta que sigue es cómo @PersistenceContext puede inyectar Entity Manager solo cuando comienza el contenedor, suponiendo que el ciclo de vida del gerente de entidad sea corto y requiere múltiples administradores de entidades por solicitud.
La respuesta es que no puede: EntityManager es una interfaz, y lo que se inyecta en el Spring Bean no es el propio administrador de entidades, sino el proxy consciente del contexto (proxy consciente del contexto) del administrador de entidades específico en el tiempo de ejecución.
La clase específica comúnmente utilizada para el proxy es SharedEntityManagerInVocationHandler, que puede confirmarse con la ayuda de un depurador.
Entonces, ¿cómo funciona @Transactional?
El proxy de contexto persistente que implementa la interfaz EntityManager no es la única parte de la gestión de transacciones declarativas, pero en realidad contiene tres componentes:
EntityManager proxy en sí mismo
La sección de la transacción
Administrador de transacciones
Eche un vistazo a estas tres partes y sus interacciones.
La sección de la transacción
La sección de transacción es una sección "alrededor" que se puede llamar antes y después del método comercial anotado. La clase específica que implementa la sección es Transaction Interceptor.
Hay dos responsabilidades principales en la sección de una transacción:
En 'antes', la sección proporciona un punto de llamada para decidir si el método comercial llamado debe ejecutarse dentro del alcance de la transacción en curso o iniciar una nueva transacción independiente.
En 'After', la sección necesita determinar que la transacción se comete, se retrocede o continúe ejecutándose.
En 'antes', la sección de transacciones en sí no contiene ninguna lógica de decisión, y la decisión de iniciar una nueva transacción se delega al administrador de transacciones para su finalización.
Administrador de transacciones
El administrador de transacciones debe resolver los siguientes dos problemas:
¿Debería crearse el nuevo gerente de entidad?
¿Debería iniciarse una nueva transacción?
Estos requieren que las secciones de transacción se determinen cuando se llama a la lógica 'antes'. Las decisiones del administrador de transacciones se basan en los siguientes dos puntos:
¿Está sucediendo la transacción?
La propiedad de propagación del método de transacción (por ejemplo, requiere_new siempre inicia una nueva transacción)
Si el administrador de transacciones determina que desea crear una nueva transacción, lo hará:
1. Cree un nuevo gerente de entidad
2. El Administrador de intientidades está vinculado al hilo actual
3. Obtenga conexión desde el grupo de conexión de la base de datos
4. Vincula la conexión al hilo actual
Use la variable ThreadLocal para unir tanto al administrador de entidad como la conexión de la base de datos al subproceso actual.
Las transacciones se ejecutan cuando se almacenan en el hilo, y cuando ya no están en uso, el administrador de transacciones decide si las eliminar.
Cualquier parte del programa se puede recuperar del hilo si se requiere el administrador de entidad actual y la conexión de la base de datos.
EntityManager proxy
EntityManager proxy (ya introducido anteriormente) es la última parte del rompecabezas. Cuando el método comercial llama a EntityManager.persist (), esto no es llamado directamente por el gerente de entidad.
En cambio, el método comercial llama al agente, que obtiene el gerente de entidad actual del hilo. Como se mencionó anteriormente, el administrador de transacciones une al administrador de entidad al hilo.
Después de comprender las diversas partes del mecanismo @Transactional, echemos un vistazo a las configuraciones de resorte comúnmente utilizadas que lo implementan.
Integrar tres partes
¿Cómo combinar tres partes para que las anotaciones de transacción puedan funcionar correctamente? Primero defina la fábrica de Entity Manager.
Esto le permite inyectar el poder del administrador de entidades con anotación de contexto de persistencia.
@Configuration publicClass EntityManagerFactoryConfiguration {@aUtowired privateTataSource dataSource; @Bean (name = "entityManagerFactory") publicLocalContainerEnTityManagerFactoryBean emf () {localContainerEnTityMangerFactoryBean emf = ... emf.setTataSource (DataSource); Newstring [] {"Your.package"}); emf.SetJpavendorAdapter (newHibernateJpavendorAdapter ()); returnemf;}}El siguiente paso es configurar el Administrador de transacciones y aplicar las facetas de la transacción en la clase anotada @Transactional.
@Configuration @EnabletransactionManagement PublicClass TransactionManageRsConfig {@aUtoWired EntityManagerFactory emf; @autewired privatedataSource dataSource; @Bean (name = "transaccionManager") publicplatFormTransactionManager TransactionManager () {jpatransactionManager tm = newJPatransActionManager (); TM.SetEntityManagerFactory (EMF); TM.SetDataSource (DataSource); returnm;}}La anotación @enabletransactionManagement notifica la primavera que la clase anotada por @Transactional está rodeada por el corte de la transacción. De esta manera se puede usar @Transactional.
Resumir
El mecanismo de gestión de transacciones declarativo de Spring es muy poderoso, pero se puede utilizar mal o ser errores fácilmente configurados.
Cuando problemas como este mecanismo no funcionan correctamente o no logran los resultados operativos esperados, es útil comprender sus trabajos internos.
Lo más importante a recordar es tener en cuenta dos conceptos: transacciones y contextos de persistencia, cada uno con su propio ciclo de vida obvio que es ilegible.
Lo anterior es todo el contenido de este artículo sobre el principio de funcionamiento de Spring @Transactional. Espero que sea útil para todos. Los amigos interesados pueden continuar referiéndose a otros temas relacionados en este sitio. Si hay alguna deficiencia, deje un mensaje para señalarlo. ¡Gracias amigos por su apoyo para este sitio!