La "perspectiva de Dios" ilustra el principio del mecanismo de propagación de las transacciones de Spring.

Las "manos" de las


transacciones de la base de datos La función de transacción de la base de datos ha sido implementada por la propia base de datos y deja al usuario con tres instrucciones: abrir la transacción, confirmar la transacción y revertir la transacción.

Iniciar transacción es generalmente iniciar una transacción o comenzar una transacción. Las transacciones de compromiso se suelen confirmar. Las transacciones de reversión suelen ser reversibles.

Las bases de datos suelen tener interruptores para abrir y confirmar transacciones automáticamente. Después de abrir, la transacción se abrirá y confirmará o revertirá automáticamente. De esta forma, el usuario no se da cuenta.


JDBC "manos" de transacciones


JDBC implementa el protocolo para acceder a la base de datos, que puede considerarse como una encapsulación de algunas instrucciones, por supuesto, incluidas estas instrucciones de transacción. Todos se realizan en la interfaz java.sql.Connection.

Representa una conexión a la base de datos.Cuando se establece la conexión, la transacción predeterminada ya está abierta y la transacción se confirma automáticamente después de ejecutar una instrucción SQL por defecto.

Se puede detectar a través de la siguiente API:

boolean getAutoCommit ();

Normalmente, no queremos que la transacción se confirme una por una, sino ejecutar varias sentencias SQL y confirmarla a la vez. En este momento, necesitamos cambiar esta confirmación automática el comportamiento de.

Se puede configurar mediante la siguiente API:

void setAutoCommit (boolean autoCommit);

cuando deshabilitamos el autocommit, debemos recordar realizar la transacción manualmente, de lo contrario se puede imaginar el resultado. Por supuesto, recuerde retroceder manualmente cuando necesite retroceder.

Puede enviar la transacción a través de la siguiente API:

void commit ();

Puede revertir la transacción a través de la siguiente API:

void rollback ();

De esta forma, podemos controlar el comportamiento de la transacción a nivel de código Java. Al mismo tiempo, también debemos darnos cuenta de que las transacciones a nivel de código Java están vinculadas al objeto de instancia de Connecton.

En otras palabras, solo las instrucciones SQL ejecutadas en el mismo objeto Connection estarán en la misma transacción. Las sentencias SQL ejecutadas en diferentes objetos Connection nunca estarán en la misma transacción.

Más precisamente, la última constituye una transacción distribuida y la primera suele denominarse transacción local. Por supuesto, las transacciones distribuidas tienen sus propias soluciones, pero las transacciones locales ya no se pueden utilizar.

Observaciones : Lo anterior es en realidad sentido común básico, pero el marco ORM actual es demasiado bueno, por lo que muchos programadores jóvenes no tienen la oportunidad de contactarlos .


La transacción de Spring "manos"


Spring implementa transacciones declarativas mediante el uso de anotaciones @Transactional, y puede afectar las características de propagación de las transacciones estableciendo el atributo Propagation.

La característica de propagación de la transacción en realidad significa que cuando varios métodos de la capa de servicio se entrelazan entre sí, qué código de método se ejecuta en la misma transacción y qué código de método no.

Del análisis anterior, se puede ver que el código de método ejecutado en la misma transacción debe usar el mismo objeto Connection, cuando la transacción es conmutada, el objeto Connection detrás de ella debe cambiarse al correspondiente.

Por lo tanto, cuando el proceso de ejecución ingresa / sale de diferentes métodos, Spring cambiará el objeto Connection detrás del correspondiente de acuerdo con las características de propagación de las anotaciones en el método, incluida la creación de un nuevo objeto Connection, el envío o la reversión de una transacción, etc.

Sabemos que al escribir el método de capa de servicio o el método de capa de mapeador, el objeto de conexión no es accesible en absoluto, por lo que es aún más imposible pasarlo de un lado a otro en forma de parámetros de forma descarada, y solo se puede operar en la oscuridad.

Dado que estos códigos de método entrelazados eventualmente se ejecutan en el mismo hilo, es más adecuado usar el ThreadLocal del hilo para implementar la operación detrás de él.

Simplemente cree / cambie el objeto Connection en la entrada / salida de la llamada al método y envíe / revertir la transacción en el objeto Connection.


El principio de las características de propagación de las


transacciones Spring Las transacciones Spring se implementan a través de agentes, generalmente a través del bytecode de manipulación CGLIB para generar subclases, porque estos códigos para abrir / confirmar transacciones deben agregarse dinámicamente.

El siguiente es un ejemplo para ilustrar que hay cuatro métodos y sus correspondientes características de propagación:

Método uno, la característica de propagación es REQUERIDA: método

void1 ();

Método dos, la característica de propagación es REQUERIDA: método

void2 ();

Método tres, la característica de propagación es REQUIRES_NEW:

void method3 ();

Método cuatro, la característica de propagación es REQUERIDA:

void method4 ();

Suponiendo que la relación de llamada entre ellos es que el método dos, tres y cuatro se llaman secuencialmente en el método uno:

void método1 () {     método2 ();     método3 ();     method4 (); } se puede representar mediante la siguiente figura, figura 01:






 


Luego, después de que Spring genere un proxy, cada método se reescribirá y la transacción se abrirá antes de cada método original, y la transacción se confirmará / revertirá después del método.

El pseudocódigo equivalente es el siguiente:

beginTx ();
void method1 () {     beginTx ();     method2 ();     commit / rollbackTx ();     beginTx ();     method3 ();     commit / rollbackTx ();     beginTx ();     method4 ( );     commit / rollbackTx (); } commit / rollbackTx (); puede ser representado por la siguiente figura, figura 02:













 


La flecha roja hacia arriba corresponde a la operación beginTx () y la flecha azul hacia abajo corresponde a la operación commit / rollbackTx ().

Echemos un vistazo al proceso de ejecución específico:

1. Inicie la transacción del método de ejecución 1, Figura 03:
 


Dado que el primer método requiere una transacción, no hay ninguna transacción en el subproceso en este momento, por lo que se abre una nueva transacción, es decir, se crea un nuevo objeto Connection y se vincula al ThreadLocal del subproceso.

2. El método de entrada se ejecuta al principio, Figura 04:
 


3. Ejecute la transacción abierta del Método 2, Figura 05:
 


Dado que el segundo método requiere una transacción, ya existe una transacción en el hilo en este momento, por lo que puede participar o utilizar directamente esta transacción.

4. Ingrese el método dos y comience la ejecución, Figura 06:
 


En quinto lugar, se completa el método 2 para ejecutar la transacción de confirmación, Figura 07:
 


Dado que la transacción no se creó recientemente en el método dos, solo participa, por lo que no es elegible para enviar la transacción, por lo que en realidad no envía la transacción.

6. Una vez finalizado el método dos, vuelva al método uno para ejecutarlo, Figura 08:
 


Siete, ejecute el método tres para abrir la transacción, Figura 09:
 


Debido a que el método tres requiere cosas nuevas, se crea una nueva transacción y se suspende la transacción actual existente para que el hilo actual use la nueva transacción.

Es decir, cree un nuevo objeto Connection, desvincule el objeto Connection actual existente del ThreadLocal del subproceso y vincule el nuevo objeto Connection al ThreadLocal del subproceso.

¿Qué pasa con el objeto Connection original? Por supuesto, se almacena y la forma de almacenamiento se adjunta al nuevo objeto Connection, es decir, se asocia con el nuevo objeto.

8. Ingrese el método tres y comience la ejecución, Figura 10:
 


Puede verse que la transacción original equivale a almacenarse temporalmente en la nueva transacción. Tenga en cuenta que esta afirmación es solo una metáfora de imagen.

Nueve, se completa el método tres para ejecutar la transacción de confirmación, Figura 11:
 


Dado que esta transacción es una transacción nueva, es decir, se creó mediante el método tres en lugar de participar, por lo que tiene derecho a comprometerse, por lo que la transacción está realmente comprometida.

10. Después del método tres, vuelva al método uno para ejecutarlo, Figura 12:
 


La transacción del método 3 se completa, pero la transacción del método 1 se almacena temporalmente en ella, por lo que se restaura en el hilo.

11. Realice la transacción de apertura del Método 4, Figura 13:
 


Dado que el método 4 requiere una transacción, ya existe una transacción en el hilo en este momento, por lo que puede participar o usar directamente esta transacción.

12. Ingrese el método 4 y comience la ejecución, Figura 14:
 


13. Se completa el método 4 para ejecutar la transacción de confirmación, Figura 15:
 


Dado que la transacción no se crea recientemente mediante el método cuatro, solo participa, por lo que no es elegible para enviar la transacción, por lo que en realidad no envía la transacción.

14. Después del método cuatro, vuelva al método uno para su ejecución, Figura 16:
 


Quince, se completa el método uno para ejecutar la transacción de confirmación, Figura 17:
 


Dado que esta transacción es una transacción nueva, es decir, se crea mediante el método uno en lugar de participar, por lo que tiene derecho a comprometerse, por lo que la transacción realmente se compromete.

16. Todas las transacciones se completan y solo queda un hilo vacío, Figura 18:
 


Se completa la transacción del método 1. Como no hay otras transacciones almacenadas temporalmente en él, no hay más transacciones, por lo que solo queda un hilo vacío.

Nota : Esta es solo la comprensión original de la implementación de la función de propagación, por lo que es relativamente simple y la implementación del código real debe considerar muchas cosas, por lo que será mucho más complicado.

 

Supongo que te gusta

Origin blog.csdn.net/weixin_45132238/article/details/108710750
Recomendado
Clasificación