[Spring Boot 23] Gestión de transacciones MyBatis

I. Resumen

La gestión de transacciones es esencial para las aplicaciones empresariales. Incluso si hay una situación anormal, también puede garantizar la coherencia de los datos.
Spring Framework proporciona una abstracción coherente para la gestión de transacciones y sus características son las siguientes:

Proporcionar un modelo de programación coherente para diferentes API de transacciones, como JTA (Java Transaction API), JDBC, Hibernate, JPA (Java Persistence API y JDO (Java Data Objects), admitir la gestión de transacciones declarativas, especialmente la gestión de transacciones declarativas basada en anotaciones , Simple y fácil de usar Proporciona una API de gestión de transacciones programática más simple que otras API de transacciones como JTA, y la integración perfecta de la abstracción de acceso a datos de Spring.

2. Método de gestión de transacciones

Spring admite dos formas de administración de transacciones programáticas y administración de transacciones declarativas.

La gestión programática de transacciones utiliza TransactionTemplateo utiliza directamente el subyacente PlatformTransactionManager. Spring lo recomienda para la gestión de transacciones programáticas TransactionTemplate.

La gestión declarativa de transacciones se basa en AOP. Su esencia es interceptar antes y después del método, y luego crear o agregar una transacción antes de que comience el método de destino, y enviar o revertir la transacción de acuerdo con la ejecución después de que se ejecute el método de destino. La mayor ventaja de las transacciones declarativas es que no necesitan ser administradas por programación, por lo que no es necesario dopear el código de administración de transacciones en el código de lógica empresarial, y solo es necesario realizar declaraciones de reglas de transacción relevantes en el archivo de configuración (o mediante @Transactionalanotaciones Way), puede aplicar reglas de transacción a la lógica empresarial.

Obviamente, la gestión declarativa de transacciones es mejor que la gestión programática de transacciones, que es el método de desarrollo no intrusivo que propugna Spring. La gestión declarativa de transacciones mantiene el código empresarial libre de contaminación Un objeto POJO ordinario puede obtener soporte completo para transacciones añadiendo anotaciones. En comparación con las transacciones programáticas, la única desventaja de las transacciones declarativas es que la granularidad más fina de estas últimas solo se puede aplicar al nivel de método y no se puede aplicar al nivel de bloque de código como las transacciones programáticas. Pero incluso si existe tal demanda, existen muchas soluciones, por ejemplo, el bloque de código que debe ser la gestión de transacciones puede ser independiente como método, etc.

También hay dos formas comunes de administración de transacciones declarativas, una se basa en el archivo de configuración xml de los espacios de nombres tx y aop, y la otra se basa en @Transactionalanotaciones. Obviamente, el método basado en anotaciones es más simple, más fácil de usar y más refrescante.

Tres, características de la transacción de primavera

Todas las clases de estrategias de gestión de transacciones de primavera heredan de la org.springframework.transaction.PlatformTransactionManagerinterfaz

public interface PlatformTransactionManager {
 
  TransactionStatus getTransaction(TransactionDefinition definition)
    throws TransactionException;
 
  void commit(TransactionStatus status) throws TransactionException;
 
  void rollback(TransactionStatus status) throws TransactionException;
}

Además de especificar diferentes administradores de transacciones, también puede controlar el nivel de aislamiento y el comportamiento de propagación de la transacción, que se explican en detalle a continuación:

Cuatro, nivel de aislamiento

El nivel de aislamiento se refiere al grado de aislamiento entre varias transacciones concurrentes Los principales escenarios relacionados con nuestro desarrollo incluyen: lecturas sucias, lecturas repetidas y lecturas fantasmas.
Para lectura sucia, lectura no repetible y lectura fantasma, consulte: ¿Qué es lectura sucia, lectura no repetible, lectura fantasma?

Podemos ver org.springframework.transaction.annotation.Isolationque cinco valores que representan el nivel de aislamiento están definidos en la clase de enumeración:

public enum Isolation {
    DEFAULT(-1),
    READ_UNCOMMITTED(1),
    READ_COMMITTED(2),
    REPEATABLE_READ(4),
    SERIALIZABLE(8);
}
  • DEFAULT: Este es el valor predeterminado, lo que significa que se utiliza el nivel de aislamiento predeterminado de la base de datos subyacente. Para la mayoría de las bases de datos, este valor suele ser: READ_COMMITTED.
  • READ_UNCOMMITTED: este nivel de aislamiento significa que una transacción puede leer datos modificados por otra transacción pero que aún no se han confirmado. Este nivel no puede evitar lecturas sucias y lecturas no repetibles, por lo que este nivel de aislamiento rara vez se usa.
  • READ_COMMITTED: este nivel de aislamiento significa que una transacción solo puede leer datos que han sido confirmados por otra transacción. Este nivel puede evitar lecturas sucias, que también es el valor recomendado en la mayoría de los casos.
  • REPEATABLE_READ: este nivel de aislamiento significa que una transacción puede ejecutar una consulta varias veces durante todo el proceso, y los registros devueltos cada vez son los mismos. Incluso si hay nuevos datos para satisfacer la consulta entre varias consultas, estos nuevos registros se ignorarán. Este nivel puede evitar lecturas sucias y lecturas no repetibles.
  • SERIALIZABLE: Todas las transacciones se ejecutan una a una, por lo que no hay interferencia entre transacciones, es decir, este nivel puede evitar lecturas sucias, lecturas no repetibles y lecturas fantasmas. Pero esto afectará seriamente el desempeño del programa. Normalmente tampoco se utiliza este nivel.

Especificar método: establecer mediante la propiedad de aislamiento, por ejemplo:

@Transactional(isolation = Isolation.DEFAULT)

5. Comportamiento comunicativo

El llamado comportamiento de propagación de transacciones significa que si ya existe un contexto de transacción antes de iniciar la transacción actual, existen varias opciones para especificar el comportamiento de ejecución de un método transaccional.

Podemos ver org.springframework.transaction.annotation.Propagationque 6 valores de enumeración que representan el comportamiento de propagación están definidos en la clase de enumeración:

public enum Propagation {
    REQUIRED(0),
    SUPPORTS(1),
    MANDATORY(2),
    REQUIRES_NEW(3),
    NOT_SUPPORTED(4),
    NEVER(5),
    NESTED(6);
}
  • OBLIGATORIO: Si actualmente hay una transacción, únase a la transacción; si no hay una transacción actual, cree una nueva transacción.
  • SOPORTE: Si actualmente hay una transacción, únase a la transacción; si no hay una transacción actual, continúe ejecutándose de manera no transaccional.
  • OBLIGATORIO: Si hay una transacción actualmente, únase a la transacción; si no hay ninguna transacción actualmente, se lanza una excepción.
  • REQUIRES_NEW: Cree una nueva transacción, si hay una transacción actualmente, suspenda la transacción actual.
  • NOT_SUPPORTED: se ejecuta en un modo no transaccional. Si hay una transacción actualmente, la transacción actual se suspende.
  • NUNCA: Ejecutar en modo no transaccional. Si hay una transacción actualmente, se lanza una excepción.
  • ANIDADO: Si actualmente hay una transacción, cree una transacción para ejecutar como una transacción anidada de la transacción actual; si no hay una transacción actual, el valor es equivalente a REQUERIDO.

Especificar método: se establece mediante el atributo de propagación, por ejemplo:

@Transactional(propagation = Propagation.REQUIRED)

Seis, tiempo de espera de transacción

El llamado tiempo de espera de la transacción se refiere al tiempo máximo que se permite ejecutar una transacción. Si se excede el límite de tiempo pero la transacción no se ha completado, la transacción se revierte automáticamente. El valor int se usa para representar el tiempo de espera en TransactionDefinition, y la unidad es segundos.

La configuración predeterminada es el valor de tiempo de espera del sistema de transacciones subyacente. Si el sistema de transacciones de la base de datos subyacente no establece un valor de tiempo de espera, entonces no es ninguno y no hay límite de tiempo de espera.

Siete, atributos de transacción de solo lectura

Las transacciones de solo lectura se usan cuando el código del cliente es de solo lectura pero no modifican los datos. Las transacciones de solo lectura se usan para la optimización en escenarios específicos, como cuando se usa Hibernate.
El valor predeterminado es leer y escribir transacciones.

Ocho, reglas de reversión de transacciones de primavera

La forma recomendada de instruir al administrador de transacciones de Spring para revertir una transacción es lanzar una excepción en el contexto de la transacción actual. El administrador de transacciones de Spring detectará las excepciones no controladas y luego decidirá si revertir la transacción que genera la excepción de acuerdo con las reglas.

En la configuración predeterminada, Spring revierte la transacción solo cuando la excepción lanzada es una excepción no comprobada en tiempo de ejecución, es decir, la excepción lanzada es una subclase de RuntimeException (los errores también harán que la transacción retroceda), y se lanza una excepción marcada. No hará que la transacción se revierta.
Puede configurar explícitamente para revertir la transacción cuando se lanzan esas excepciones, incluidas las excepciones marcadas. También puede definir claramente aquellas transacciones que no se revierten cuando se lanzan excepciones.

También puede utilizar mediante programación el método setRollbackOnly () para indicar que una transacción debe revertirse. La única operación que puede realizar después de llamar a setRollbackOnly () es revertir.

Nueve, @Anotación transaccional

uso

@Transactional puede actuar sobre interfaces, métodos de interfaz, clases y métodos de clase. Cuando se usa como una clase, todos los métodos públicos de la clase tendrán el atributo de transacción de este tipo. Al mismo tiempo, también podemos usar esta anotación a nivel de método para anular la definición de nivel de clase.

Aunque la anotación @Transactional se puede aplicar a interfaces, métodos de interfaz, clases y métodos de clase, Spring recomienda no usar esta anotación en interfaces o métodos de interfaz, porque solo tendrá efecto cuando se utilicen proxies basados ​​en interfaz. Además, la anotación @Transactional solo debe aplicarse a métodos públicos, que está determinada por la naturaleza de Spring AOP. Si usa la anotación @Transactional en métodos de visibilidad protegidos, privados o predeterminados, esto se ignorará y no se lanzará ninguna excepción.

De forma predeterminada, el proxy AOP solo capturará las llamadas a métodos externos, es decir, los métodos dentro de una clase que llaman a otros métodos dentro de esta clase no causarán un comportamiento transaccional, incluso si el método llamado es modificado por la anotación @Transactional.

Antes de usar la anotación @Transactional, agregue la anotación @EnableTransactionManagement a la clase de inicio para iniciar la transacción.

@EnableTransactionManagement  //开启事务
public class AdminApplication {

    public static void main(String[] args) {
        SpringApplication.run(AdminApplication.class, args);
    }

}

Nota: El
proxy dinámico de Java utiliza un mecanismo de reflexión para generar una clase anónima que implementa la interfaz de proxy y llama a InvokeHandler para procesarla antes de llamar a métodos específicos.

El proxy dinámico cglib usa el paquete de código abierto asm para cargar el archivo de clase de la clase de objeto proxy y procesarlo modificando su código de bytes para generar subclases.

1. Si el objeto de destino implementa la interfaz, el proxy dinámico del JDK se utilizará para implementar AOP de forma predeterminada.
2. Si el objeto de destino implementa la interfaz, puede forzar el uso de CGLIB para implementar AOP
3. Si el objeto de destino no implementa la interfaz, debe usar la biblioteca CGLIB. Spring cambiará automáticamente entre el proxy dinámico JDK y CGLIB

Supongo que te gusta

Origin blog.csdn.net/guorui_java/article/details/109088823
Recomendado
Clasificación