La principale recherche de cet article est la propagation des transactions Spring et ses principes de mise en œuvre, qui sont introduits comme suit.
Spring est actuellement une norme de facto pour le développement de Java, grâce à sa commodité, ses fonctions complètes et à l'utilisation facile à utiliser. Pendant le processus de développement, l'exploitation de la base de données est une opération très courante et en ce qui concerne la DB, elle implique des transactions. Pendant le processus de développement normal des transactions, même si vous ne le remarquez pas, il n'y aura aucun effet secondaire sur l'exécution normale du programme. Cependant, si une exception se produit et que la transaction n'est pas gérée correctement, des résultats inattendus peuvent se produire. Spring a encapsulé diverses opérations en termes de transactions, en particulier l'émergence de transactions déclaratives, ce qui rend le développement plus confortable. Spring étend les transactions et prend en charge la définition de plusieurs attributs de propagation, qui est également au centre de cet article.
Pas à proprement parler, une transaction est l'abréviation de plusieurs opérations. Ces opérations prennent effet, soit aucune d'entre elles ne prend effet (équivalent à ne pas être exécutée). Un processus de fonctionnement général est simplifié comme suit:
essayez {connexion conn = getConnection (); // effectuer certaines opérations de base de données} catch (exception e) {conn.rollback ();} enfin {conn.close ();}Certains problèmes peuvent être vus à partir du code ci-dessus:
Spring fournit des transactions déclaratives, nous n'avons donc pas à prêter attention à l'implémentation spécifique de la couche sous-jacente et bloque de nombreux détails de mise en œuvre différents de la couche sous-jacente. Afin de prendre en charge le contrôle fin des transactions par plusieurs entreprises complexes, Spring fournit les attributs de propagation des transactions et combinée avec des transactions déclaratives, il est devenu un outil de transaction majeur.
Dans la classe TransactionDefinition, Spring fournit 6 propriétés de propagation, qui sont expliquées avec des exemples simples.
Rappel chaud: la jonction mentionnée suivante de la transaction actuelle fait référence à l'utilisation de la même connexion en bas, mais l'objet d'état de transaction peut être recréé et ne l'affecte pas. L'article a mentionné qu'il n'y a actuellement qu'une seule transaction, ce qui signifie que la connexion sous-jacente est partagée et ne se soucie pas du nombre d'objets d'état de transaction (TransactionStatus).
Description: Si une transaction existe déjà, rejoignez la transaction. S'il n'y a pas de transaction, créez une transaction. Il s'agit de la valeur d'attribut de propagation par défaut.
Voyons un petit exemple, le code est le suivant:
@TransactionalPublic Void Service () {Servicea (); ServiceB ();} @ TransactionalServicea (); @ TransactionalServiceB ();Servicea et ServiceB déclarent les deux transactions. Par défaut, propagation = propagation_requied. Pendant l'ensemble du processus d'appel de service, il n'y a qu'une seule transaction partagée. Lorsqu'une exception se produit, toutes les opérations seront annulées.
Description: Si une transaction existe déjà, rejoignez la transaction, sinon une transaction dite vide est créée (elle peut être considérée comme une exécution de transaction).
Voyons un petit exemple, le code est le suivant:
public void Service () {Servicea (); lancer un nouveau runtimeException ();} @ transactionnel (propagation = propagation.supports) Servicea ();Il n'y a actuellement aucune transaction lorsque Servicea s'exécute, de sorte que l'exception jetée dans le service ne fera pas la randonnée de Servicea.
Jetons un coup d'œil à un autre petit exemple, le code est le suivant:
public void Service () {Servicea ();} @ transactional (propagation = propagation.supports) Servicea () {do SQL 1 1/0; faire SQL 2}Étant donné que Servicea n'a pas de transactions lors de l'exécution, pour le moment, si la source de données sous-jacente defauftAutoCommit = true, alors SQL1 est efficace. Si defaultAutoCommit = false, alors SQL1 n'est pas valide. Si le service a la balise @Transactional, Servicea partage les transactions de service (ne comptez plus sur DefaultAutoCommit). À l'heure actuelle, Servicea est tout en arrière.
Description: Une transaction doit actuellement exister, sinon une exception sera lancée.
Voyons un petit exemple, le code est le suivant:
public void Service () {ServiceB (); Servicea ();} ServiceB () {do SQL} @Transactional (propagation = propagation.mandatory) Servicea () {do SQL}Dans ce cas, l'exécution du service lancera une exception. Si defaultAutoCommit = true, ServiceB ne reviendra pas. Si defaultAutoCommit = false, l'exécution de ServiceB ne sera pas valide.
Remarque: Si une transaction existe actuellement, encapsulez d'abord le contenu actuel lié à la transaction dans une entité, puis recréez une nouvelle transaction, acceptez cette entité comme paramètre et utilisez-la pour la récupération de transaction. Une instruction plus émoussée consiste à suspendre la transaction actuelle (aucune transaction n'est nécessaire) et créer une nouvelle transaction. Dans ce cas, il n'y a pas de dépendance entre les deux transactions, et la nouvelle transaction peut être annulée, mais la transaction externe continue de s'exécuter.
Voyons un petit exemple, le code est le suivant:
@TransactionalPublic void Service () {ServiceB (); essayez {Servicea (); } catch (exception e) {}} ServiceB () {do Sql} @Transactional (propagation = propagation.requires_new) Servicea () {do Sql 1 1/0; faire SQL 2}Lors de l'appel de l'interface de service, puisque Servicea utilise Deals_new, il créera une nouvelle transaction. Cependant, parce que Servicea lance une exception d'exécution, Servicea est annulée. Dans la méthode de service, des exceptions sont prises, donc ServiceB est soumis normalement. Notez que le code d'essai ... Catch dans le service est nécessaire, sinon le service lancera une exception, ce qui entraînera le retour du serviceB.
Remarque: Si une transaction existe actuellement, suspendre la transaction actuelle, puis la nouvelle méthode est exécutée dans un environnement sans transactions et dans un environnement sans transactions Spring, le commit de SQL dépend complètement de la valeur de propriété de DefaultAutoCommit.
Voyons un petit exemple, le code est le suivant:
@TransactionalPublic void Service () {ServiceB (); Servicea ();} ServiceB () {do SQL} @Transactional (propagation = propagation.not_supported) Servicea () {do Sql 1 1/0; faire SQL 2}Lorsque la méthode de service est appelée, une exception est lancée lorsque le code 1/0 de la méthode Servicea est exécuté. Étant donné que Servicea se trouve dans un environnement sans transaction, si SQL1 est efficace dépend de la valeur de la valeur de DefaultoToCommit. Lorsque defaultAutoCommit = TRUE, SQL1 est efficace, mais ServiceB sera annulé car le service lance une exception.
Description: Si une transaction est actuellement présente, une exception est lancée, sinon le code est exécuté sur un environnement sans transaction.
Voyons un petit exemple, le code est le suivant:
public void Service () {ServiceB (); Servicea ();} ServiceB () {do SQL} @Transactional (propagation = propagation.never) Servicea () {do Sql 1 1/0; faire SQL 2}Après l'exemple ci-dessus des appels, si defaultAutoCommit = true, la méthode ServiceB et SQL1 dans Servicea prendra effet.
Remarque: Si une transaction existe actuellement, utilisez la technologie SavePoint pour enregistrer l'état de transaction actuel, puis la couche sous-jacente partage une connexion. Lorsqu'une erreur se produit à l'intérieur, elle reviendra à l'état de sauvegarde en soi. Tant qu'une exception est prise par l'extérieur, elle peut continuer à engager des transactions externes sans être dérangée par l'entreprise intégrée. Cependant, si une exception est lancée par la transaction externe, l'ensemble de la grande transaction sera annulée.
Remarque: Le gestionnaire de transaction de configuration de Spring doit spécifier activement NeedTransactionAllowed = true, comme indiqué ci-dessous:
<bean id = "dataTransactionManager"> <propriété name = "dataSource" ref = "datadatasource" /> <propriété name = "NeedTransactionAllowed" value = "true" /> </-bean>
Voir un petit exemple, le code est le suivant:
@TransactionalPublic Void Service () {Servicea (); essayez {ServiceB (); } catch (exception e) {}} Servicea () {do SQL} @Transactional (propagation = propagation.nest) ServiceB () {do Sql1 1/0; faire sql2}ServiceB est un service intégré et une exception d'exécution est lancée en interne, donc ServiceB est annulé. Étant donné que le service a fait l'exception, Servicea peut le soumettre normalement.
Jetons un coup d'œil à un autre exemple, le code est le suivant:
@TransactionalPublic Void Service () {Servicea (); ServiceB (); 1/0;} @ transactionnel (propagation = propagation.nest) Servicea () {do SQL} ServiceB () {do SQL}Étant donné que le service lance une exception, l'intégralité de la méthode de service sera annulée. (Ceci est différent de Propagation_Requires_New. Les services intégrés en mode imbriqué seront annulés par des exceptions des transactions externes.)
Les exemples ci-dessus illustrent plusieurs attributs de propagation fournis par Spring Transactions sont utilisés pour répondre à une variété de besoins commerciaux différents, qui peuvent être déterminés par l'entreprise. Ensuite, examinons les dépendances techniques les plus importantes du printemps implémentent ces attributs de propagation. Cette section répertorie Propagation_Requires_New et Propagation.Festées pour les brèves descriptions respectivement.
L'appel de code suivant:
@TransactionalPublic void Service () {ServiceB (); essayez {Servicea (); } catch (exception e) {}} @ transactional (propagation = propagation.requires_new) Servicea () {do Sql 1 1/0; do SQL 2} ServiceB () {do SQL}Le schéma d'exécution est le suivant:
un. Créez un objet d'état de transaction, obtenez une nouvelle connexion, réinitialisez l'autoCommit, récupérez la taille, le délai d'expiration et d'autres propriétés de la connexion
né Lier la connexion à la variable threadlocal
c. En attendant la transaction actuelle, encapsulant l'objet d'état de transaction actuel, la connexion et d'autres informations dans un objet SuspendeResources, qui peut être utilisé pour la reprise
d. Créez un nouvel objet d'état de transaction, réacquièrez une nouvelle connexion, réinitialisez l'autocommit, récupérer la taille, le délai d'expiration et d'autres propriétés de la nouvelle connexion. Dans le même temps, enregistrez l'objet SuspendeSources pour la récupération de transaction et liez la nouvelle connexion à la variable threadlocal (opération d'écrasement)
e. Assistez à une exception, reculez la connexion dans ThreadLocal, restaurez les paramètres de connexion, fermez la connexion et restaurez les suspendeResources
f. Soumettez la connexion dans la variable threadLocal (provoquant la soumission du service B), restaurez les paramètres de connexion, fermez la connexion et renvoyez la connexion à la source de données
Le résultat de l'exécution du programme est donc que Servicea est annulé et que ServiceB est soumis avec succès.
L'appel de code suivant:
@TransactionalPublic Void Service () {Servicea (); essayez {ServiceB (); } catch (exception e) {}} Servicea () {do SQL} @Transactional (propagation = propagation.nest) ServiceB () {do Sql1 1/0; faire sql2}Le schéma d'exécution est le suivant:
un. Créez un objet d'état de transaction, obtenez une nouvelle connexion, réinitialisez l'autoCommit, récupérez la taille, le délai d'expiration et d'autres propriétés de la connexion
né Lier la connexion à la variable threadlocal
c. Marquez l'utilisation de l'objet d'état de transaction actuel, obtenez l'objet de connexion ThreadLocal, enregistrez le point de sauvegarde de la connexion actuelle et est utilisé pour la récupération des exceptions. Pour le moment, le point de sauvegarde est le statut après l'exécution du Servicea
d. Assistez à une exception et utilisez SavePoint en C pour le retour en arrière de la transaction, c'est-à-dire en retournant l'état à l'état après avoir exécuté Servicea. Toutes les exécutions des méthodes ServiceB ne prennent pas en vigueur
e. Obtenez l'objet de connexion dans ThreadLocal, Soumettre les transactions, restaurer les propriétés de connexion, Closez Connection
Sur la base de la source de données sous-jacente, Spring utilise ThreadLocal, SavePoint et d'autres points techniques pour réaliser une variété d'attributs de propagation de transaction, ce qui facilite la mise en œuvre de divers services complexes. Ce n'est qu'en comprenant le principe des attributs de propagation que nous pouvons mieux contrôler les transactions de printemps. Les transactions de retour en arrière reposent sur la capture des exceptions. Par défaut, les transactions ne seront annulées que si la conception et l'erreur RuntimeExe sont lancées. Bien sûr, il peut être configuré. Pour plus d'informations, vous pouvez consulter l'annotation @transactionnelle.
Les transactions déclaratives de Spring nous apportent une grande commodité. Afin de faire bon usage de cette arme, il est toujours nécessaire de comprendre les principes sous-jacents. Cet article n'est que la pointe de l'iceberg des transactions de printemps. Les lecteurs peuvent explorer en profondeur sur cette base.
Ce qui précède est tout le contenu de cet article sur la propagation des transactions Spring et ses principes de mise en œuvre. J'espère que ce sera utile à tout le monde. Les amis intéressés peuvent continuer à se référer à d'autres sujets connexes sur ce site. S'il y a des lacunes, veuillez laisser un message pour le signaler. Merci vos amis pour votre soutien pour ce site!