[Spring Boot 23] Gestion des transactions MyBatis

I. Aperçu

La gestion des transactions est essentielle pour les applications d'entreprise. Même en cas de situation anormale, elle peut également garantir la cohérence des données.
Spring Framework fournit une abstraction cohérente pour la gestion des transactions, et ses caractéristiques sont les suivantes:

Fournit un modèle de programmation cohérent pour différentes API de transaction, telles que JTA (Java Transaction API), JDBC, Hibernate, JPA (Java Persistence API et JDO (Java Data Objects), prend en charge la gestion déclarative des transactions, en particulier la gestion déclarative des transactions basée sur les annotations , Simple et facile à utiliser Fournit une API de gestion des transactions programmatique plus simple que les autres API de transaction telles que JTA, intégration parfaite avec l'abstraction d'accès aux données de printemps.

2. Méthode de gestion des transactions

Spring prend en charge deux méthodes de gestion programmatique des transactions et de gestion déclarative des transactions.

La gestion programmatique des transactions utilise TransactionTemplateou utilise directement le sous-jacent PlatformTransactionManager. Pour la gestion des transactions programmatiques, Spring le recommande TransactionTemplate.

La gestion des transactions déclaratives est basée sur l'AOP. Son essence est d'intercepter avant et après la méthode, puis de créer ou d'ajouter une transaction avant le démarrage de la méthode cible, et de soumettre ou d'annuler la transaction en fonction de l'exécution après l'exécution de la méthode cible. Le plus grand avantage des transactions déclaratives est qu'elles n'ont pas besoin d'être gérées par programmation, il n'est donc pas nécessaire de doper le code de gestion des transactions dans le code de logique métier, et il suffit de faire les déclarations de règles de transaction pertinentes dans le fichier de configuration (ou via des @Transactionalannotations Way), vous pouvez appliquer des règles de transaction à la logique métier.

De toute évidence, la gestion déclarative des transactions est meilleure que la gestion programmatique des transactions, qui est la méthode de développement non intrusive préconisée par Spring. La gestion déclarative des transactions protège le code métier de la pollution. Un objet POJO ordinaire peut bénéficier d'une prise en charge complète des transactions en ajoutant des annotations. Par rapport aux transactions programmatiques, le seul inconvénient des transactions déclaratives est que la granularité la plus fine de ces dernières ne peut être appliquée qu'au niveau de la méthode, et ne peut pas être appliquée au niveau du bloc de code comme les transactions programmatiques. Mais même s'il existe une telle demande, il existe de nombreuses méthodes alternatives, par exemple, les blocs de code qui doivent être la gestion des transactions peuvent être indépendants en tant que méthodes, etc.

Il existe également deux méthodes courantes de gestion déclarative des transactions, l'une est basée sur le fichier de configuration xml des espaces de noms tx et aop, et l'autre est basée sur des @Transactionalannotations. De toute évidence, la méthode basée sur les annotations est plus simple, plus facile à utiliser et plus rafraîchissante.

Trois, caractéristiques de la transaction de printemps

Toutes les classes de stratégie de gestion des transactions printanières héritent de l' org.springframework.transaction.PlatformTransactionManagerinterface

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

En plus de spécifier différents gestionnaires de transactions, vous pouvez également contrôler le niveau d'isolement et le comportement de propagation de la transaction, qui sont expliqués en détail ci-dessous:

Quatre, niveau d'isolement

Le niveau d'isolement fait référence au degré d'isolement entre plusieurs transactions simultanées. Les principaux scénarios liés à notre développement sont les suivants: lectures modifiées, lectures répétées et lectures fantômes.
Pour une lecture sale, une lecture non répétable et une lecture fantôme, voir: Qu'est-ce qu'une lecture sale, une lecture non répétable, une lecture fantôme

Nous pouvons voir org.springframework.transaction.annotation.Isolationque cinq valeurs représentant le niveau d'isolement sont définies dans la classe d'énumération:

public enum Isolation {
    DEFAULT(-1),
    READ_UNCOMMITTED(1),
    READ_COMMITTED(2),
    REPEATABLE_READ(4),
    SERIALIZABLE(8);
}
  • DEFAULT: il s'agit de la valeur par défaut, ce qui signifie que le niveau d'isolement par défaut de la base de données sous-jacente est utilisé. Pour la plupart des bases de données, cette valeur est généralement: READ_COMMITTED.
  • READ_UNCOMMITTED: Ce niveau d'isolement signifie qu'une transaction peut lire des données modifiées par une autre transaction mais pas encore validées. Ce niveau ne peut pas empêcher les lectures modifiées et les lectures non répétables, ce niveau d'isolement est donc rarement utilisé.
  • READ_COMMITTED: ce niveau d'isolement signifie qu'une transaction ne peut lire que les données qui ont été validées par une autre transaction. Ce niveau peut empêcher les lectures incorrectes, qui est également la valeur recommandée dans la plupart des cas.
  • REPEATABLE_READ: ce niveau d'isolement signifie qu'une transaction peut exécuter une requête plusieurs fois pendant tout le processus, et les enregistrements renvoyés à chaque fois sont les mêmes. Même s'il existe de nouvelles données pour répondre à la requête entre plusieurs requêtes, ces nouveaux enregistrements seront ignorés. Ce niveau peut empêcher les lectures incorrectes et les lectures non répétables.
  • SERIALIZABLE: Toutes les transactions sont exécutées une par une, de sorte qu'il n'y a pas d'interférence entre les transactions, c'est-à-dire que ce niveau peut empêcher les lectures sales, les lectures non répétables et les lectures fantômes. Mais cela affectera gravement les performances du programme. Normalement, ce niveau n'est pas utilisé non plus.

Spécifiez la méthode: définie à l'aide de la propriété isolation, par exemple:

@Transactional(isolation = Isolation.DEFAULT)

5. Comportement de communication

Le comportement dit de propagation de transaction signifie que si un contexte de transaction existe déjà avant de démarrer la transaction en cours, il existe plusieurs options pour spécifier le comportement d'exécution d'une méthode transactionnelle.

Nous pouvons voir org.springframework.transaction.annotation.Propagationque 6 valeurs d'énumération représentant le comportement de propagation sont définies dans la classe d'énumération:

public enum Propagation {
    REQUIRED(0),
    SUPPORTS(1),
    MANDATORY(2),
    REQUIRES_NEW(3),
    NOT_SUPPORTED(4),
    NEVER(5),
    NESTED(6);
}
  • OBLIGATOIRE: s'il y a une transaction actuellement, rejoignez la transaction; s'il n'y a pas de transaction actuellement, créez une nouvelle transaction.
  • SUPPORTS: S'il y a actuellement une transaction, rejoignez la transaction; s'il n'y a pas de transaction en cours, continuez à exécuter de manière non transactionnelle.
  • OBLIGATOIRE: s'il y a une transaction actuellement, rejoignez la transaction; s'il n'y a pas de transaction actuellement, une exception est levée.
  • REQUIRES_NEW: Créez une nouvelle transaction, s'il y a une transaction actuellement, puis suspendez la transaction en cours.
  • NOT_SUPPORTED: exécution en mode non transactionnel. S'il y a une transaction actuellement, la transaction en cours est suspendue.
  • JAMAIS: exécution en mode non transactionnel. S'il y a une transaction actuellement, une exception est levée.
  • NESTED: S'il y a actuellement une transaction, créez une transaction à exécuter en tant que transaction imbriquée de la transaction actuelle; s'il n'y a pas de transaction en cours, la valeur est équivalente à REQUIRED.

Spécifiez la méthode: définie à l'aide de l'attribut de propagation, par exemple:

@Transactional(propagation = Propagation.REQUIRED)

Six, délai d'expiration de la transaction

Le délai d'expiration de transaction fait référence à la durée maximale pendant laquelle une transaction est autorisée à s'exécuter. Si le délai est dépassé mais que la transaction n'est pas terminée, la transaction est automatiquement annulée. La valeur int est utilisée pour représenter le délai d'expiration dans TransactionDefinition, et l'unité est en secondes.

Le paramètre par défaut est la valeur du délai d'expiration du système de transactions sous-jacent. Si le système de transactions de la base de données sous-jacent ne définit pas de valeur de délai d'expiration, alors il n'y a aucune valeur de délai d'expiration.

Sept attributs en lecture seule de transaction

Les transactions en lecture seule sont utilisées lorsque le code client est en lecture seule mais ne modifient pas les données. Les transactions en lecture seule sont utilisées pour l'optimisation dans des scénarios spécifiques, comme lors de l'utilisation d'Hibernate.
La valeur par défaut est des transactions de lecture et d'écriture.

Huit règles de restauration des transactions de printemps

La méthode recommandée pour demander au gestionnaire de transactions Spring d'annuler une transaction consiste à lever une exception dans le contexte de la transaction en cours. Le gestionnaire de transactions Spring interceptera toutes les exceptions non gérées, puis décidera s'il faut annuler la transaction qui lève l'exception selon les règles.

Dans la configuration par défaut, Spring annule la transaction uniquement lorsque l'exception levée est une exception non vérifiée à l'exécution, c'est-à-dire que l'exception levée est une sous-classe de RuntimeException (les erreurs entraîneront également l'annulation de la transaction), et une exception vérifiée est levée. N'entraînera pas l'annulation de la transaction.
Vous pouvez explicitement configurer pour restaurer la transaction lorsque ces exceptions sont levées, y compris les exceptions vérifiées. Vous pouvez également définir clairement les transactions qui ne sont pas annulées lorsque des exceptions sont levées.

Vous pouvez également utiliser par programme la méthode setRollbackOnly () pour indiquer qu'une transaction doit être annulée. La seule opération que vous pouvez effectuer après avoir appelé setRollbackOnly () consiste à annuler.

Neuf, annotation @Transactional

usage

@Transactional peut agir sur les interfaces, les méthodes d'interface, les classes et les méthodes de classe. Lorsqu'elles sont utilisées comme classe, toutes les méthodes publiques de la classe auront l'attribut transaction de ce type. En même temps, nous pouvons également utiliser cette annotation au niveau de la méthode pour remplacer la définition au niveau de la classe.

Bien que l'annotation @Transactional puisse être appliquée aux interfaces, aux méthodes d'interface, aux classes et aux méthodes de classe, Spring recommande de ne pas utiliser cette annotation sur les interfaces ou les méthodes d'interface, car elle ne prendra effet que lorsque des proxys basés sur l'interface sont utilisés. De plus, l'annotation @Transactional ne doit être appliquée qu'aux méthodes publiques, ce qui est déterminé par la nature de Spring AOP. Si vous utilisez l'annotation @Transactional sur des méthodes de visibilité protégées, privées ou par défaut, cela sera ignoré et aucune exception ne sera levée.

Par défaut, seuls les appels de méthode de l'extérieur seront capturés par le proxy AOP, c'est-à-dire que les méthodes à l'intérieur d'une classe appelant d'autres méthodes à l'intérieur de cette classe ne provoqueront pas de comportement transactionnel, même si la méthode appelée est modifiée par l'annotation @Transactional.

Avant d'utiliser l'annotation @Transactional, veuillez ajouter l'annotation @EnableTransactionManagement à la classe de démarrage pour démarrer la transaction.

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

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

}

Remarque: Le
proxy dynamique Java utilise un mécanisme de réflexion pour générer une classe anonyme qui implémente une interface proxy et appelle InvokeHandler pour la traiter avant d'appeler des méthodes spécifiques.

Le proxy dynamique cglib utilise le package open source asm pour charger le fichier de classe de la classe d'objet proxy et le traiter en modifiant son bytecode pour générer des sous-classes.

1. Si l'objet cible implémente l'interface, le proxy dynamique du JDK sera utilisé pour implémenter AOP par défaut.
2. Si l'objet cible implémente l'interface, vous pouvez forcer l'utilisation de CGLIB pour implémenter AOP
3. Si l'objet cible n'implémente pas l'interface, vous devez utiliser la bibliothèque CGLIB. Spring basculera automatiquement entre le proxy dynamique JDK et CGLIB

Je suppose que tu aimes

Origine blog.csdn.net/guorui_java/article/details/109088823
conseillé
Classement