Maison > Java > javaDidacticiel > Introduction détaillée aux principes de transaction Spring

Introduction détaillée aux principes de transaction Spring

黄舟
Libérer: 2017-03-25 11:09:22
original
1529 Les gens l'ont consulté

1. Principes de base des transactions

L'essence des transactions Spring est en fait la prise en charge des transactions par la base de données, Spring ne peut pas fournir de fonctions de transaction. Pour une base de données d'opérations JDBC pure, si vous souhaitez utiliser des transactions, vous pouvez suivre les étapes suivantes :

  1. Obtenir la connexion Connection con = DriverManager.getConnection()

  2. Ouvrir la transaction con.setAutoCommit(true/false);

  3. Exécuter CRUD

  4. Commit transaction/rollback transaction con.commit () / con.rollback();

  5. Fermez la connexion conn.close();

Après avoir utilisé la fonction de gestion des transactions de Spring, nous Impossible ensuite d'écrire le code des étapes 2 et 4, mais il sera automatiquement complété par Spirng .Alors Spring est Comment ouvrir et fermer les transactions avant et après le CRUD que nous écrivons ?Pour résoudre ce problème, nous pouvons comprendre le principe de mise en œuvre de la gestion des transactions de Spring dans son ensemble. Présentons brièvement la méthode d'annotation à titre d'exemple

. <.>
  1. Fichier de configurationActivez l'annotationDriver et marquez les classes et méthodes pertinentes avec l'annotation @Transactional

  2. Spring analysera et générera les beans associés au démarrage, à ce moment-là, il vérifiera les classes et les méthodes avec les annotations pertinentes, générera des proxys pour ces classes et méthodes et injectera les configurations pertinentes en fonction des paramètres pertinents de @Transaction. , de sorte que l'agent gère les transactions pertinentes pour nous (permet la soumission normale des transactions et l'annulation des exceptions
  3. La véritable soumission et l'annulation des transactions de la couche de base de données se font via binlog ou redo Log.
  4. 2. Propagation des transactions Spring
Attribut

L'attribut dit de propagation de la transaction Spring est défini lorsqu'il y a plusieurs transactions en même temps . Lorsqu'elles existent, comment Spring doit gérer le comportement de ces transactions. Ces attributs sont définis dans TransactionDefinition. L'explication des

constantes

est présentée dans le tableau suivant :

.
Nom de la constante Explication de la constante
PROPAGATION_REQUIRED Prend en charge la transaction en cours S'il n'y a pas de transaction en cours, créez une nouvelle transaction. . Il s'agit du choix le plus courant et constitue la propagation des transactions par défaut de Spring.
PROPAGATION_REQUIRES_NEW Nouvelle transaction, s'il existe actuellement une transaction, Suspendre la transaction en cours. La transaction nouvellement créée n'aura rien à voir avec la transaction suspendue. Ce sont deux transactions indépendantes. Après l'échec de la transaction externe et son annulation, les résultats de l'exécution de la transaction interne ne peuvent pas être annulés. "http: //www.php.cn/php/php-tp-throw.html" target="_blank">Lance une exception, capturée par la transaction externe, ou ne traite pas l'opération de restauration
PROPAGATION_SUPPORTS Prend en charge la transaction en cours s'il n'y a actuellement aucune transaction. , il sera exécuté de manière non transactionnelle.
PROPAGATION_MANDATORY Prend en charge la transaction en cours s'il n'y a pas transaction en cours, une exception est levée.
PROPAGATION_NOT_SUPPORTED Effectuer des opérations de manière non transactionnelle if S'il y a actuellement une transaction, la transaction en cours est suspendue.
PROPAGATION_NEVER Exécuter en mode non transactionnel, si le courant Si une transaction existe, une exception est levée.
PROPAGATION_NESTED

Si une transaction active existe, s'exécute dans une transaction imbriquée. S'il n'y a aucune transaction active, l'attribut REQUIRED est exécuté. Il utilise une seule transaction avec plusieurs points de sauvegarde pouvant être annulés. L'annulation des transactions internes n'affectera pas les transactions externes. Cela ne fonctionne que sur le gestionnaire de transactions DataSourceTransactionManager.

3. Niveau d'isolement de la base de données

隔离级别 隔离级别的值 导致的问题
Read-Uncommitted 0 导致脏读
Read-Committed 1 避免脏读,允许不可重复读和幻读
Repeatable-Read 2 避免脏读,不可重复读,允许幻读
Serializable 3 串行化读,事务只能一个一个执行,避免了脏读、不可重复读、幻读。执行效率慢,使用时慎重

Lecture sale : une transaction a ajouté, supprimé ou modifié des données, mais elle n'a pas été soumise. Une autre transaction peut lire les données non validées. Si la première transaction est annulée à ce moment-là, la deuxième transaction lira les données sales.

Lecture non répétable : deux opérations de lecture se sont produites dans une transaction. Entre la première opération de lecture et la deuxième opération, une autre transaction a modifié les données. À ce moment, les données lues deux fois sont incohérentes.

Lecture fantôme : la première transaction regroupe les modifications d'une certaine plage de données, et la deuxième transaction ajoute une donnée à cette plage. À ce moment, la première transaction perdra la modification des données nouvellement ajoutées. .

Résumé :

Plus le niveau d'isolement est élevé, plus les données peuvent être complètes et cohérentes, mais plus l'impact sur les performances de concurrence est grand.

Le niveau d'isolement par défaut de la plupart des bases de données est Lecture validée, comme SqlServer, Oracle

Le niveau d'isolement par défaut de quelques bases de données est : Lecture répétable, telle que : MySQL InnoDB

4. Niveau d'isolement au printemps

常量 解释
ISOLATION_DEFAULT 这是个 PlatfromTransactionManager 默认的隔离级别,使用数据库默认的事务隔离级别。另外四个与 JDBC 的隔离级别相对应。
ISOLATION_READ_UNCOMMITTED 这是事务最低的隔离级别,它充许另外一个事务可以看到这个事务未提交的数据。这种隔离级别会产生脏读,不可重复读和幻像读。
ISOLATION_READ_COMMITTED 保证一个事务修改的数据提交后才能被另外一个事务读取。另外一个事务不能读取该事务未提交的数据。
ISOLATION_REPEATABLE_READ 这种事务隔离级别可以防止脏读,不可重复读。但是可能出现幻像读。
ISOLATION_SERIALIZABLE 这是花费最高代价但是最可靠的事务隔离级别。事务被处理为顺序执行。

5. Imbrication des transactions

Grâce aux connaissances théoriques ci-dessus, nous avons une compréhension approximative de certains attributs et caractéristiques des transactions de base de données et des transactions printanières, pour comprendre en profondeur les scénarios de transactions imbriquées. mécanisme de propagation des transactions printanières.

Supposons que la méthode A() du service de transaction externe A appelle la méthode B() du service interne B

PROPAGATION_REQUIRED (printemps par défaut)

Si le niveau de transaction de ServiceB.methodB() est défini comme PROPAGATION_REQUIRED, alors spring a déjà initié une transaction lors de l'exécution de ServiceA.methodA(). À ce moment, ServiceB.methodB() est appelé et ServiceB.methodB() le voit. est déjà en cours d'exécution dans ServiceA. Dans la transaction de methodA(), aucune nouvelle transaction ne sera initiée.

Si ServiceB.methodB() constate qu'il n'est pas dans une transaction lors de son exécution, il s'attribuera une transaction pour lui-même.

De cette façon, si une exception se produit n'importe où dans ServiceA.methodA() ou ServiceB.methodB(), la transaction sera annulée.

PROPAGATION_REQUIRES_NEW

Par exemple, nous concevons le niveau de transaction de ServiceA.methodA() comme étant PROPAGATION_REQUIRED et le niveau de transaction de ServiceB.methodB() comme étant PROPAGATION_REQUIRES_NEW .

Ensuite, lorsque ServiceB.methodB() sera exécuté, la transaction où se trouve ServiceA.methodA() sera suspendue et ServiceB.methodB() démarrera une nouvelle transaction, en attendant ServiceB.methodB() après la transaction est terminée, elle continue son exécution.

La différence entre celui-ci et PROPAGATION_REQUIRED est le degré d'annulation de la transaction. Étant donné que ServiceB.methodB() démarre une nouvelle transaction, il existe deux transactions différentes. Si ServiceB.methodB() a été soumis, alors ServiceA.methodA() échoue et revient en arrière, mais ServiceB.methodB() ne revient pas en arrière. Si ServiceB.methodB() ne parvient pas à revenir en arrière, si l'exception levée est interceptée par ServiceA.methodA(), la transaction ServiceA.methodA() peut toujours être soumise (cela dépend principalement si l'exception levée par B est une exception que A va revenir en arrière) .

PROPAGATION_SUPPORTS

Supposons que le niveau de transaction de ServiceB.methodB() est PROPAGATION_SUPPORTS, puis lorsque ServiceB.methodB() est exécuté, s'il s'avère que ServiceA. methodA() a été Lorsqu'une transaction est ouverte, rejoignez la transaction en cours S'il s'avère que ServiceA.methodA() n'ouvre pas la transaction, il n'ouvrira pas la transaction elle-même. À l’heure actuelle, le caractère transactionnel de la méthode interne dépend entièrement de la transaction la plus externe.

PROPAGATION_NESTED

Maintenant, la situation devient plus compliquée. L'attribut de transaction de ServiceB.methodB() est configuré comme PROPAGATION_NESTED. À ce stade, il y aura Comment collaborer. ? ServiceB#methodB En cas d'annulation, la transaction interne (c'est-à-dire ServiceB#methodB) sera restaurée vers le SavePoint avant son exécution, tandis que la transaction externe (c'est-à-dire ServiceA#methodA) peut être traitée des deux manières suivantes :

a. Capturez les exceptions et exécutez la logique de branche d'exception

void methodA() { 

        try { 

            ServiceB.methodB(); 

        } catch (SomeException) { 

            // 执行其他业务, 如 ServiceC.methodC(); 

        } 

    }
Copier après la connexion

Cette méthode est également la partie la plus précieuse des transactions imbriquées. Elle a pour effet d'exécuter une branche. ServiceC est exécuté methodC() et ServiceB.methodB est revenu au SavePoint avant son exécution, donc aucune donnée sale ne sera générée (équivalent au fait que cette méthode ne sera jamais exécutée). Cette fonctionnalité peut être utilisée dans certaines entreprises spéciales. et PROPAGATION_REQUIRED Ni PROPAGATION_REQUIRES_NEW ni PROPAGATION_REQUIRES_NEW ne peuvent faire cela.

b. Le code d'annulation/de validation de la transaction externe n'apporte aucune modification, puis si la transaction interne (ServiceB#methodB) est annulée, alors ServiceB.methodB revient d'abord au SavePoint avant son exécution (dans n'importe quel Dans ce cas), la transaction externe (c'est-à-dire ServiceA#methodA) décidera de valider ou d'annuler en fonction de la configuration spécifique

Les trois autres attributs de propagation de transaction ne sont fondamentalement pas utilisés et ne seront pas analysés ici.

6. Résumé

Pour les endroits où des transactions doivent être utilisées dans le projet, je recommande aux développeurs de toujours utiliser l'interface TransactionCallback de Spring pour implémenter les transactions. N'utilisez pas aveuglément les annotations de transaction Spring si vous. doit utiliser Remarque, vous devez avoir une compréhension détaillée du mécanisme de propagation des transactions Spring et du niveau d'isolement, sinon des effets inattendus peuvent survenir.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Étiquettes associées:
source:php.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal