Cet article effectuera des recherches approfondies sur la gestion des transactions de Spring. Introduit principalement le fonctionnement de @Transactional en bas. L'article suivant vous présentera:
Utilisation d'attributs tels que la propagation (propagation des transactions) et l'isolement (isolement)
Quels sont les pièges de l'utilisation des transactions et comment l'éviter
JPA et gestion des transactions
Il est important que le JPA lui-même ne fournit aucune sorte de gestion des transactions déclaratives. Si vous utilisez JPA en dehors d'un conteneur d'injection de dépendance, la transaction doit être implémentée par programme par le développeur.
Usertransaction utx = entityManager.getTransaction (); try {utx.begin (); businessLogic (); utx.Commit ();} catch (exception ex) {utx.rollback (); lancex;}Cette façon de gestion des transactions permet à la portée des transactions d'être clairement exprimée dans le code, mais elle a les inconvénients suivants:
Le code et les erreurs répétés sont sujets à
Toutes les erreurs peuvent avoir un impact plus important
Les erreurs sont difficiles à déboguer et à reproduire
Réduit la lisibilité de la base de code
Et si la méthode appelle d'autres méthodes de transaction?
Utilisation de Spring @Transactional
En utilisant Spring @Transactional, le code ci-dessus est simplifié à:
@Transactional PublicVoid BusinessLogic () {... Utilisez Entity Manager dans une transaction ...}Le code est plus concis et lisible, et c'est aussi le moyen recommandé de traiter à l'heure actuelle.
De nombreux aspects importants tels que la propagation des transactions peuvent être gérés automatiquement en utilisant @Transactional. Dans ce cas, si BusinessLogic () appelle une autre méthode de transaction, la méthode déterminera comment rejoindre la transaction en cours en fonction des options.
Un inconvénient potentiel de ce mécanisme puissant est qu'il masque l'opération sous-jacente et est difficile à déboguer lorsqu'il ne fonctionne pas correctement.
@Transactional Signification
L'un des points clés de @Transactional est de considérer deux concepts distincts, qui ont tous deux leur propre portée et cycle de vie:
Contexte de persistance (contexte de persistance)
transaction de base de données
@Transactional lui-même définit la portée d'une seule transaction. Cette transaction se situe dans le cadre du contexte de persistance.
Le contexte de persistance dans JPA est EntityManager, et l'implémentation interne utilise la session Hibernate (en utilisant Hibernate comme fournisseur de persistance).
Le contexte de persistance n'est qu'un objet synchrone qui enregistre l'état des objets Java d'une collection finie et garantit que les changements dans ces objets sont finalement persistés dans la base de données.
Il s'agit d'un concept très différent d'une seule transaction. Un gestionnaire d'entité peut être utilisé sur plusieurs transactions, et il est en effet utilisé de cette manière.
Quand EntityManager couvre-t-il plusieurs transactions?
La situation la plus courante est lorsqu'une application utilise une session ouverte en mode View pour gérer les exceptions d'initialisation paresseuses. Les articles précédents ont introduit les avantages et les inconvénients de cette approche.
Dans ce cas, plusieurs requêtes exécutées par la couche de vue sont dans des transactions distinctes, plutôt que dans une logique métier à transaction unique, mais ces requêtes sont gérées par le même gestionnaire d'entité.
Un autre scénario est que le développeur marque le contexte de persistance comme persistancecontextType.extended, ce qui signifie qu'il est capable de répondre à plusieurs demandes.
Comment définir la relation entre EntityManager et Transaction?
Ceci est choisi par les développeurs d'applications, mais le moyen le plus courant pour JPA Entity Manager est le mode "Entity Manager par application Transaction". Les méthodes courantes d'injection du gestionnaire d'entité sont:
@PersistenceContext privatentityManager EM;
La valeur par défaut est le mode "Entity Manager par transaction". Dans ce mode, si le gestionnaire d'entité est utilisé dans la méthode @Transactional, la méthode s'exécutera en une seule transaction.
Comment fonctionne @persistenceContext?
La question qui suit est de savoir comment @PerSistenceContext ne peut injecter Entity Manager uniquement lorsque le conteneur démarre, en supposant que le cycle de vie du gestionnaire d'entité est court et nécessite plusieurs gestionnaires d'entités par demande.
La réponse est qu'il ne peut pas: EntityManager est une interface, et ce qui est injecté dans le bean de printemps n'est pas le gestionnaire d'entité lui-même, mais le proxy de contexte (proxy conscient de contexte) du gestionnaire d'entité spécifique dans l'exécution.
La classe spécifique couramment utilisée pour le proxy est SharedEntityManageRerinvocationHandler, qui peut être confirmée à l'aide d'un débogueur.
Alors, comment fonctionne @Transactional?
Le proxy de contexte persistant qui implémente l'interface EntityManager n'est pas la seule partie de la gestion des transactions déclaratives, mais contient en fait trois composantes:
Proxy entitymanager lui-même
La section de la transaction
Gestionnaire de transactions
Jetez un œil à ces trois parties et à leurs interactions.
La section de la transaction
La section de transaction est une section "autour" qui peut être appelée avant et après la méthode commerciale annotée. La classe spécifique qui implémente la section est Transaction Interceptor.
Il y a deux principales responsabilités dans la section d'une transaction:
Dans «avant», la section fournit un point d'appel pour décider si la méthode commerciale appelée doit s'exécuter dans le cadre de la transaction en cours ou démarrer une nouvelle transaction indépendante.
Dans «After», la section doit déterminer que la transaction est engagée, reculée ou a continué à s'exécuter.
Dans «Avant», la section des transactions elle-même ne contient aucune logique de décision et la décision de démarrer une nouvelle transaction est déléguée au gestionnaire de transactions pour l'achèvement.
Gestionnaire de transactions
Le gestionnaire de transactions doit résoudre les deux problèmes suivants:
Le nouveau gestionnaire d'entité devrait-il être créé?
Une nouvelle transaction doit-elle être démarrée?
Ceux-ci nécessitent des sections de transaction à déterminer lorsque la logique «avant» est appelée. Les décisions du gestionnaire de transactions sont basées sur les deux points suivants:
La transaction se déroule-t-elle
La propriété de propagation de la méthode de transaction (par exemple, Deibles_new démarre toujours une nouvelle transaction)
Si le gestionnaire de transactions détermine que vous souhaitez créer une nouvelle transaction, elle sera:
1. Créez un nouveau gestionnaire d'entité
2. Le gestionnaire d'intimité est lié au thread actuel
3. Obtenez la connexion à partir du pool de connexions de la base de données
4. Liber la connexion au thread actuel
Utilisez la variable ThreadLocal pour lier à la fois le Manager Entity Manager et la connexion de la base de données au thread actuel.
Les transactions s'exécutent lorsqu'ils sont stockés dans le thread et lorsqu'ils ne sont plus utilisés, le gestionnaire de transactions décide de les effacer.
Toute partie du programme peut être récupérée à partir du thread si le gestionnaire d'entité actuel et la connexion de la base de données sont nécessaires.
Proxy entité
EntityManager Proxy (déjà introduit plus tôt) est la dernière partie du puzzle. Lorsque la méthode commerciale appelle entityManager.persiste (), cela n'est pas appelé directement par le gestionnaire d'entité.
Au lieu de cela, la méthode commerciale appelle l'agent, qui obtient le gestionnaire d'entité actuel du thread. Comme mentionné précédemment, le gestionnaire de transactions lie le gestionnaire d'entité au thread.
Après avoir compris les différentes parties du mécanisme @transactionnel, jetons un coup d'œil aux configurations de ressort couramment utilisées qui les implémentent.
Intégrer trois parties
Comment combiner trois parties pour que les annotations de transaction puissent fonctionner correctement? Définissez d'abord l'usine du gestionnaire d'entités.
Cela vous permet d'injecter un proxy du gestionnaire d'entité avec l'annotation du contexte de persistance.
@Configuration publicClass EntityManagerFactoryConfiguration {@Autowired privatedAtaSource DataSource; @Bean (name = "EntityManagerFactory") publicLocalContainerEntityManagerFactoryBean EMF () {localContainerentityManagerFactoryBean EMF = ... ... EMF.SetDataSource (DataSource); EMF.SetPackArestoscan (Newstring [] {"your.package"}); emf.setjPavendorAdapter (newHiberNateJPavendArAdapter ()); returnMf;}}L'étape suivante consiste à configurer le gestionnaire de transactions et à appliquer les facettes de transaction dans la classe annotée @Transactional.
@Configuration @enableTransactionManagement publicClass TransactionManagersConfig {@Autowired EntityManagerFactory EMF; @Autowired PrivateDataSource DataSource; @Bean (name = "TransactionManager") PublicPlatformTransactionManager TransactionManager () {JPatransactionManager TM = newjpatransactionManager (); tm.SetEntityManagerFactory (EMF); tm.setDataSource (dataSource); returnm;}}Annotation @enableTransactionManagement informe le printemps que la classe annotée par @transactional est entourée de la coupe de la transaction. De cette façon, @Transactional peut être utilisé.
Résumer
Le mécanisme de gestion des transactions déclaratifs de Spring est très puissant, mais il peut être utilisé à mauvais escient ou des erreurs facilement configurées.
Lorsque des problèmes tels que ce mécanisme ne fonctionnent pas correctement ou ne parviennent pas à obtenir les résultats de fonctionnement attendus, il est utile de comprendre son fonctionnement interne.
La chose la plus importante à retenir est de prendre en compte deux concepts: les transactions et les contextes de persistance, chacun avec son propre cycle de vie évident qui est illisible.
Ce qui précède est tout le contenu de cet article sur le principe de travail de Spring @Transactional. 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!