Préface
Cet article enregistre principalement comment le printemps prend en charge les choses, et comment peut-il simplement implémenter les fonctions des choses de la base de données lorsque le printemps combine mybatis. Je n'en dirai pas grand-chose ci-dessous, jetons un coup d'œil à l'introduction détaillée ensemble.
Cas1: les choses soutiennent la situation dans deux tables
Préparez d'abord deux tables, une table utilisateur et une table d'histoire, la structure est la suivante
Créer la table `User` (` id` int (11) non signé non null auto_increment, `name` varchar (20) pas null '' comment« commentaire »,` pwd »varchar (26) pas null` `commentaire '' mot de passe», `isdeteted» tinyint (1) non null '0', `` créé ' varchar (13) non null par défaut '0', clé primaire (`id`), clé` name` (`name`)) moteur = innodb par défaut charset = utf8mb4; créer la table` sténée` (`id` int (11) non signé null auto_increment,` `userd` int (20) non signé non pas par défaut '0' comment '' `` Commentaire '' auteur ', `` title' varchar (26) pas null par défaut '' comment 'mot de passe', `` histor '' commentaire de texte 'contenu d'histoire' ', `` Isdeleted' tinyint (1) pas null default '0', `` créé 'varchar (13) pas null default' 0 ', `` Mis à jour' Varchar (13) Null '0', Key primaire (id '), id' '(`` utilisateur' '). Moteur = innodb par défaut Charset = UTF8MB4;
Notre situation est que lorsque l'utilisateur modifie le nom, les noms des deux tables doivent être modifiés ensemble et les incohérences ne sont pas autorisées.
Case2: Support de table de table unique
Transférer de l'argent, un utilisateur réduit de l'argent, un autre utilisateur augmente de l'argent
Créer la table `` Money '(`id` int (11) non signé non null auto_increment,` name` varchar (20) pas null par défaut' 'comment `` nom d'utilisateur' ', `` argent' int (26) non null '0' comment `` argent '', `isdeteted 'tinyint (1) non null' 0 ',` `Créé' '(13) Not non par défaut' 0 ',' 0 ''. Non null par défaut '0', clé primaire (`id`), key` name` (`name`)) moteur = innodb default charset = utf8mb4;
Par rapport au cas ci-dessus, cela est plus simple. Les exemples suivants sont principalement expliqués sur la base de cela. Quant à Case1, il doit être élargi.
Tout d'abord, implémentez le DAO et l'entité correspondants
@Datapublic Class Moneyentity implémente série {private static final long SerialVersionUID = -7074788842783160025l; INT PRIVÉ ID; nom de chaîne privé; L'argent int privé; INT privé isdéréé; INT privé créé; private int mises à jour;} interface publique MoneyDao {MoneyEntity QueryMoney (@param ("id") int userId); // Ajouter de l'argent, lorsqu'il est négatif, cela signifie réduire de l'argent incrément INCMÉMENTMoney (@param ("id") int userId, @param ("addmoney") int addmoney);}Le fichier de mappel correspondant est
<? xml version = "1.0" Encoding = "UTF-8"?> <! Doctype Mappep Public "- // Mybatis.org//dtd Mapper 3.0 // en" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"><Mapper namespace = "com.git.hui.demo.mybatis.mapper.moneydao"> <sql id = "moneryentity"> id, `name`,` money`, `isdeleted`,` Created`, `Met à jour` </ sql> <Select id =" queryMoney " resultType = "com.git.hui.demo.mybatis.entity.moneyEntity"> SELECT <inclure refid = "Moneyentity" /> From Money Where id = # {id} </lect> <update id = "incrémentMoney"> update Money Set Money = Money + # {addmoney} où id = # {} </fateding> </ mawer>La configuration correspondante de la source de données de connexion MyBatis
<Ean> <propriété name = "Locations"> <value> ClassPath *: JDBC.Properties </value> </prophed> </ank> <bean id = "dataSource" init-méthod = "init" destren-méthod = "close"> <propriété name = "DriverClassname" value = "$ {driver}" /> <propriété name = "url" value = "value =" $ {url} " name = "username" value = "$ {username}" /> <propriété name = "mot de passe" value = "$ {mot de passe}" /> <propriété name = "filters" value = "stat" /> <propriété name = "maxactive" value = "20" /> <propriété name = "initialSize" value = "1" /> <propriété name = "maxwait" value = "60000" /> <prepperne name = "maxwait" value = "60000" /> <wom = "MinIdle" Value = "1" /> <propriété name = "timebetweenvictionrunsmillis" value = "60000" /> <propriété name = "MineVictableIdleMemillis" value = "300000" /> <propriété name = "validationQuery" value = "SELECT 'X'" /> <propriété name = "Test WhileIdle" value = "true" /> <propriété Nom = "Testonbrunpor" name = "testonborrow" value = "false" /> <propriété name = "testonreturn" value = "false" /> <propriété name = "poolPreparedStations" value = "true" /> <propriété name = "maxpoolPreparedStationPerConnectionsize" value = "50" /> </ bean> <bean id = "sqlSessionfactory"> <propriété = "dataource" Ref = "DataSource" /> <! - Spécifiez le fichier de mappeur -> <propriété name = "MAPTERLOCATIONS" Value = "CLASSPATH *: MAPPER / *. XML" /> </ Bean> <! - Spécifiez Scan Dao -> <Eban> <propriété Name = "BASEPACKAGE" Value = "com.git.hui.demo.mybatis" /> </ bean>Grâce à la requête en ligne, il existe quatre façons de gérer les choses du printemps. Voici des démonstrations un par un, comment jouer chaque méthode, puis voir comment choisir dans le projet réel
Gestion de la programmation, qui réalise la gestion de la chose de plusieurs opérations de base de données via TransactionTemplate
un. Mise en œuvre
Ensuite, notre cas de transfert peut être mis en œuvre comme suit
@RepositoryPublic Class CodeDemo1 {@Autowired Private Moneydao Moneydao; @Autowired Private TransactionTemplate TransactionTemplate; / ** * transfert * * @param inuserid * @param ouserured * @param paymoney * @param status 0 indique un transfert normal, 1 indique qu'une exception est lancée en interne, 2 indique un nouveau thread, modifier l'argent d'InUserrid + 200, 3 indique un nouveau thread, modifier l'argent de l'OutUserrid + 200 * / public Vende Transforment (final int dans USERID status) {transactionTemplate.Execute (new TransactionCallBackWithouTResult () {Protected void doIntransactionwithouTResult (TransactionStatus TransactionStatus) {Moneyentity Entity = MoneyDao.QueryMoney (vous pouvez transférer de l'argent / / entity.getMoney ()> PayMoney) {// Vous pouvez transférer de l'argent / / réduction de l'argent d'abord Moneydao.incrementMoney (OutUserid, -PayMoney); } // Voici tous les cas de test connexes Private Void TestCase (final int inUserId, final int ouserUsid, final int status) {if (status == 1) {lancez new illégalArgumentException ("Exception de transfert !!!"); } else if (status == 2) {addMoney (inUserId); essayez {thread.sleep (3000); } catch (InterruptedException e) {e.printStackTrace (); }} else if (status == 3) {addMoney (ouUserid); essayez {thread.sleep (3000); } catch (InterruptedException e) {e.printStackTrace (); }}} public void addMoney (final int userId) {System.out.printf ("AddMoney en interne:" + System.CurrentTimemillis ()); Nouveau thread (new Runnable () {public void run () {MoneyDao.inCrementMoney (Userid, 200); System.out.println ("sub modificateur Success! Now:" + System.Currenttimemillis ());}}). start (); }}Regardez principalement la méthode de transformation ci-dessus. L'encapsulation des choses est réalisée via TransactionTemplate en interne. Il y a trois opérations DB en interne, une requête et deux mises à jour. L'analyse spécifique sera expliquée plus tard.
Le code ci-dessus est relativement simple. La seule chose à laquelle vous devez faire attention est de savoir comment le bean transactionmplate est défini. Si vous ne collez pas le fichier XML et les précédents, collez simplement le code clé. L'un est le transactionManager créé sur la base de DataSource, et l'autre est le transactionTemplate créé sur la base de TransactionManager.
<! - Programmation des choses -> <bean id = "TransactionManager"> <propriété name = "dataSource" ref = "dataSource" /> </ bean> <bean id = "TransactionTemplate"> <propriété name = "transactionManager" ref = "TransactionManager" /> </ bean>
né Cas de test
Situation de démonstration normale, la démonstration n'a pas d'exceptions et la situation de concurrence n'est pas considérée
@Runwith (springjunit4classrunner.class) @contextConfiguration ({"classpath *: printemps / service.xml", "classpath *: test-datasource1.xml"}) classe publique CodeDemo1Test {@autowired private codedemo1 codedemo1; @Autowired Private Moneydao Moneydao; @Test public void testTransfor () {System.out.println ("----------------------"); System.out.println ("ID: 1 Money =" + MoneyDao.QueryMoney (1) .getMoney ()); System.out.println ("ID: 2 Money =" + MoneyDao.QueryMoney (2) .getMoney ()); CodeDemo1.transfor (1, 2, 10, 0); System.out.println ("-----------------------"); System.out.println ("ID: 1 Money =" + MoneyDao.QueryMoney (1) .getMoney ()); System.out.println ("ID: 2 Money =" + MoneyDao.QueryMoney (2) .getMoney ()); }}La sortie est la suivante, il n'y a aucun problème avec l'argent des deux comptes
--------------------------------------------------------------------------------------------------------------------------------
ID: 1 argent = 10000
ID: 2 argent = 50000
Le transfert est terminé! Maintenant: 1526130394266
--------------------------------------------------------------------------------------------------------------------------------
ID: 1 argent = 10010
ID: 2 Money = 49990
Une anomalie se produit pendant le processus de transfert, en particulier lorsque le cédant a déduit l'argent et que le destinataire n'a pas reçu l'argent, c'est-à-dire la situation où le statut dans l'affaire est 1.
// L'exception interne jetant @TestPublic void testTransForexception () {System.out.println ("----------------------"); System.out.println ("ID: 1 Money =" + MoneyDao.QueryMoney (1) .getMoney ()); System.out.println ("ID: 2 Money =" + MoneyDao.QueryMoney (2) .getMoney ()); try {CodeDemo1.transfor (1, 2, 10, 1); } catch (exception e) {e.printStackTrace (); } System.out.println ("---------------------------"); System.out.println ("ID: 1 Money =" + MoneyDao.QueryMoney (1) .getMoney ()); System.out.println ("ID: 2 Money =" + MoneyDao.QueryMoney (2) .GetMoney ());}À cet égard, nous espérons retourner l'argent du cédant et le sortir comme suit. Nous avons constaté qu'aucun des deux de l'argent n'avait changé.
--------------------------------------------------------------------------------------------------------------------------------
ID: 1 argent = 10010
ID: 2 Money = 49990
--------------------------------------------------------------------------------------------------------------------------------
ID: 1 argent = 10010
Java.lang.ILLEGALARgumentException: exception de transfert !!!
... // omettre les informations d'exception
ID: 2 Money = 49990
Lorsque le statut est de 2, cela signifie qu'entre l'argent du cédant a été déduit et que l'argent du bénéficiaire n'a pas été reçu, quelqu'un a transféré 200 au bénéficiaire. À l'heure actuelle, selon le mécanisme de verrouillage de MySQL, le transfert de l'autre personne doit être immédiatement reçu (car le compte du bénéficiaire n'est pas verrouillé), et il ne devrait y avoir aucun problème avec le montant.
Le résultat de sortie est le suivant:
--------------------------------------------------------------------------------------------------------------------------------
ID: 1 argent = 10010
ID: 2 Money = 49990
## À droite est une note: Pendant le processus de transfert, l'argent a été déposé immédiatement, et l'argent a été ajouté à l'intérieur n'est pas verrouillé: 1526130827480
Sub modifier le succès! Maintenant: 1526130827500
## Le transfert est terminé après avoir économisé de l'argent! Maintenant: 1526130830488
--------------------------------------------------------------------------------------------------------------------------------
ID: 1 argent = 10220
ID: 2 Money = 49980
Lorsque le statut est de 3, cela signifie que l'argent du cédant a été déduit et que l'argent du bénéficiaire n'a pas été reçu et que quelqu'un a transféré 200 au cédant. À l'heure actuelle, car l'enregistrement du cédant et le verrouillage d'écriture sont ajoutés, il ne peut qu'attendre que le transfert soumette le transfert pour réussir avant le succès de +200. Bien sûr, le montant final doit également être le même.
Le résultat de sortie est le suivant
--------------------------------------------------------------------------------------------------------------------------------
ID: 1 argent = 10220
ID: 2 Money = 49980
## à droite est une note: j'ai économisé de l'argent en interne, mais il n'a pas réussi immédiatement
## Ce n'est que lorsque le transfert est terminé qu'il réussit immédiatement. Faites attention à l'ajout d'argent à deux horodatages: 1526131101046
Le transfert est terminé! Maintenant: 1526131104051
Sub modifier le succès! Maintenant: 1526131104053
--------------------------------------------------------------------------------------------------------------------------------
ID: 1 argent = 10230
ID: 2 Money = 50170
c. Résumé
Jusqu'à présent, des choses de programmation ont été démontrées dans un exemple. D'après le processus ci-dessus, cela donne aux gens le même sentiment que d'écrire des choses liées à SQL.
démarrer la transaction;
- Ceci est la logique à l'intérieur de la méthode d'exécution de transactionTemplate #
- c'est-à-dire un ensemble de SQL qui nécessite la gestion des chosescommettre;
Les trois suivants sont la gestion de la chose déclarative, qui est moins utilisée car chaque classe de gestion doit être ajoutée à une transactionproxyfactorybean
un. Mise en œuvre
En plus de tuer TransactionTemplate et de supprimer la logique SQL interne, par rapport à la précédente, j'ai constaté qu'il n'y avait essentiellement aucune différence.
classe publique FactoryBeAndemo2 {@Autowired Private Moneydao Moneydao; / ** * transfert * * @param inuserid * @param ouserured * @param paymoney * @param status 0 indique un transfert normal, 1 indique qu'une exception a été lancée en interne, 2 indique un nouveau thread, modifier l'argent d'InUserrid + 200, 3 indique un nouveau thread, modifier l'argent de l'OutUserrid + 200 * / public Vende Transfert (final int dans USERID Status) {MoneyEntity Entity = MoneyDao.QueryMoney (OutUserId); if (entity.getMoney ()> PayMoney) {// Vous pouvez transférer de l'argent // réduire l'argent d'abord Moneydao.incrementMoney (OutUserrid, -PayMoney); TestCase (inUserrid, ouserUserid, statut); // ajouter de l'argent à Moneydao.incrementMoney (inUserId, PayMoney); System.out.println ("Le transfert est terminé! Now:" + System.Currenttimemillis ()); }} private void TestCase (final int inUserId, final int ouserUsid, final int status) {if (status == 1) {lancez new illégalargumentException ("transfert exception !!!"); } else if (status == 2) {addMoney (inUserId); essayez {thread.sleep (3000); } catch (InterruptedException e) {e.printStackTrace (); }} else if (status == 3) {addMoney (ouUserid); essayez {thread.sleep (3000); } catch (InterruptedException e) {e.printStackTrace (); }}} public void addMoney (final int userId) {System.out.println ("Interne Add Money:" + System.CurrentTimeMillis ()); Nouveau thread (new Runnable () {public void run () {MoneyDao.inCrementMoney (Userid, 200); System.out.println ("sub modificateur Success! Now:" + System.Currenttimemillis ());}}). start (); }}Le point clé est que nous devons configurer une transactionproxybeanfactory. Nous savons que BeanFactory est un moyen pour nous de créer un haricot par nous-mêmes. La configuration XML associée est la suivante
<! - Programmation des choses -> <bean id = "TransactionManager"> <propriété name = "dataSource" ref = "dataSource" /> </ bean> <bean id = "FactoryBeANDemo2" /> <! - Configurez le proxy pour la couche d'entreprise -> <Ean Id = "FactoryBeANDemoproxy"> <! - Configurez l'objet cible -> <Propriété "Target" REF = "FactoryBeAndemo2" /> <! - Inject the Transaction Manager -> <propriété name = "TransactionManager" ref = "TransactionManager" /> <! - Injecter la propriété de la transaction -> <Propriété Name = "TransactionAttributes"> <propS> <! Transactions * + Exception: quelles exceptions ne reculent pas les transactions -> <! - Cette clé correspond aux méthodes de la classe cible -> <prop key = "transfor"> propagation_required </prop> <! - <prop key = "transfert"> propagation_required, Readonly </ prop> -> <! - <prop key = "transfert"> propagation_require key = "transfert"> propagation_required, + java.lang.arithmeticexception </prop> -> </ props> </ propriété> </ bean>
Grâce à la configuration ci-dessus, nous pouvons à peu près comprendre que TransactionProxyFactoryBean crée une classe proxy de FactoryBeAndemo2. Cette classe de proxy résume la logique liée à de bonnes choses à l'intérieur, qui peut être considérée comme une simple abstraction générale de la programmation précédente.
né Test
Le code de test est fondamentalement le même qu'auparavant. La seule différence est que nous devons utiliser le haricot généré par le haricot ci-dessus, plutôt que d'utiliser directement FactoryBeAndemo2
Cas de démonstration normale:
@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration({"classpath*:spring/service.xml", "classpath*:test-datasource2.xml"})public class FactoryBeanDemo1Test { @Resource(name = "factoryBeanDemoProxy") private FactoryBeanDemo2 factoryBeanDemo2; @Autowired Private Moneydao Moneydao; @Test public void testTransfor () {System.out.println ("--------------------------"); System.out.println ("ID: 1 Money =" + MoneyDao.QueryMoney (1) .getMoney ()); System.out.println ("ID: 2 Money =" + MoneyDao.QueryMoney (2) .getMoney ()); FactoryBeAndemo2.Transfor (1, 2, 10, 0); System.out.println ("------------------------------"); System.out.println ("ID: 1 Money =" + MoneyDao.QueryMoney (1) .getMoney ()); System.out.println ("ID: 2 Money =" + MoneyDao.QueryMoney (2) .getMoney ()); }}Sortir
--------------------------------------------------------------------------------------------------------------------------------
ID: 1 argent = 10000
ID: 2 argent = 50000
Le transfert est terminé! Maintenant: 1526132058886
--------------------------------------------------------------------------------------------------------------------------------
ID: 1 argent = 10010
ID: 2 Money = 49990
Si le statut est de 1 et que l'exception interne n'est pas le cas, nous espérons qu'il n'y aura aucun problème avec l'argent.
@TestPublic void testTransForexception () {System.out.println ("---------------------------"); System.out.println ("ID: 1 Money =" + MoneyDao.QueryMoney (1) .getMoney ()); System.out.println ("ID: 2 Money =" + MoneyDao.QueryMoney (2) .getMoney ()); essayez {factoryBeAndemo2.Transfor (1, 2, 10, 1); } catch (exception e) {System.out.println (e.getMessage ()) ;; } System.out.println ("--------------------------"); System.out.println ("ID: 1 Money =" + MoneyDao.QueryMoney (1) .getMoney ()); System.out.println ("ID: 2 Money =" + MoneyDao.QueryMoney (2) .GetMoney ());}La sortie est
--------------------------------------------------------------------------------------------------------------------------------
ID: 1 argent = 10010
ID: 2 Money = 49990
Transférer une anomalie !!!
--------------------------------------------------------------------------------------------------------------------------------
ID: 1 argent = 10010
ID: 2 Money = 49990
Lorsque l'état est 2, le résultat de l'analyse doit être le même que ci-dessus, et la sortie est la suivante
--------------------------------------------------------------------------------------------------------------------------------
ID: 1 argent = 10010
ID: 2 argent = 49950
Argent interne: 1526133325376
Sub modifier le succès! Maintenant: 1526133325387
Le transfert est terminé! Maintenant: 1526133328381
--------------------------------------------------------------------------------------------------------------------------------
ID: 1 argent = 10220
ID: 2 argent = 49940
Lorsque l'état est de 3, la sortie
--------------------------------------------------------------------------------------------------------------------------------
ID: 1 argent = 10220
ID: 2 argent = 49940
Argent interne: 1526133373466
Le transfert est terminé! Maintenant: 1526133376476
Sub modifier le succès! Maintenant: 1526133376480
--------------------------------------------------------------------------------------------------------------------------------
ID: 1 argent = 10230
ID: 2 argent = 50130
c. Résumé
L'idée de TransactionProxyFactoryBean est d'utiliser le mode proxy pour implémenter la gestion des choses, générer une classe de proxy, intercepter les méthodes cibles et encapsuler un ensemble d'opérations SQL dans des choses; Par rapport au code dur, il n'est pas invasif et prend en charge les méthodes de configuration flexibles.
Les inconvénients sont également évidents, chacun doit être configuré, ce qui est assez compliqué
Le printemps a deux caractéristiques majeures: CIO et AOP. Pour des choses comme celle-ci, pouvons-nous utiliser AOP pour le faire?
Pour les méthodes qui doivent être activées, intercepter, démarrer les choses avant l'exécution, soumettre des choses après l'exécution et revenir en arrière lorsqu'une exception se produit.
De ce point de vue, cela semble assez prometteur, et les deux postures suivantes sont jouées de cette manière, donc la dépendance de l'aspect est nécessaire.
<dependency> <proupId> org.AspectJ </proupId> <ArtifActid> AspectJwweaver </letefactid> <version> 1.8.7 </-version> </pedicisse>
un. Mise en œuvre
La classe Java est exactement la même que le deuxième type, et seul le XML change
<! - Ajoutez d'abord l'espace de noms -> xmlns: tx = "http://www.springframework.org/schema/tx" xmlns: aop = "http://www.springframework.org/schema/aop" xsi: schemalocation = "... http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd"<!- Propagation: Comportement de propagation des transactions Isolement: niveau d'isolement des transactions en lecture seule: en lecture seule-retour pour: quelles exceptions se sont produites sans rappel: quelles exceptions se sont produites non pas le temps d'attente: "requis" /> </ tx: attributs> </ / tx: conseils> <! Point-Cut -> <aop: Pointcut Expression = "Execution (* com.git.hui.demo.mybatis.repository.transaction.xmldemo3. * (..))" id = "Pointcut1" /> <! - Section de configuration -> <aop: conseiller conseils-ref = "txadvice" Pointcut-ref = "Pointcut1" /> </ aop: config>
Observez la configuration ci-dessus et pensez à la deuxième méthode. L'idée est presque la même, mais cette méthode est évidemment plus générale. Grâce à la section et au point de coupe, un grand nombre de configurations peuvent être réduites.
né Test
@Runwith (springjunit4classrunner.class) @contextconfiguration ({"classpath *: printemps / service.xml", "classpath *: test-datasource3.xml"}) public class xmlbeantest {@Autowired Private XMLDemo3 xmldeMo; @Autowired Private Moneydao Moneydao; @Test public void testTransfor () {System.out.println ("----------------------"); System.out.println ("ID: 1 Money =" + MoneyDao.QueryMoney (1) .getMoney ()); System.out.println ("ID: 2 Money =" + MoneyDao.QueryMoney (2) .getMoney ()); xmldemo.transfor (1, 2, 10, 0); System.out.println ("------------------------"); System.out.println ("ID: 1 Money =" + MoneyDao.QueryMoney (1) .getMoney ()); System.out.println ("ID: 2 Money =" + MoneyDao.QueryMoney (2) .getMoney ()); }}Ce test n'est pas différent de la méthode d'écriture générale et est plus simple que la méthode d'injection de la deuxième usine
Sortie normale
--------------------------------------------------------------------------------------------------------------------------------
ID: 1 argent = 10000
ID: 2 argent = 50000
Le transfert est terminé! Maintenant: 1526135301273
--------------------------------------------------------------------------------------------------------------------------------
ID: 1 argent = 10010
ID: 2 Money = 49990
status = 1 Lorsqu'une exception se produit, la sortie est
--------------------------------------------------------------------------------------------------------------------------------
ID: 1 argent = 10010
ID: 2 Money = 49990
Transférer une anomalie !!!
--------------------------------------------------------------------------------------------------------------------------------
ID: 1 argent = 10010
ID: 2 Money = 49990
Status = 2 Le scénario d'économie d'argent pendant le processus de transfert, la sortie est cohérente avec les attentes précédentes.
--------------------------------------------------------------------------------------------------------------------------------
ID: 1 argent = 10010
ID: 2 Money = 49990
Argent interne: 1526135438403
Sub modifier le succès! Maintenant: 1526135438421
Le transfert est terminé! Maintenant: 1526135441410
--------------------------------------------------------------------------------------------------------------------------------
ID: 1 argent = 10220
ID: 2 Money = 49980
La sortie de Status = 3 est cohérente avec les attentes précédentes
--------------------------------------------------------------------------------------------------------------------------------
ID: 1 argent = 10220
ID: 2 Money = 49980
Argent interne: 1526135464341
Le transfert est terminé! Maintenant: 1526135467349
Sub modifier le succès! Maintenant: 1526135467352
--------------------------------------------------------------------------------------------------------------------------------
ID: 1 argent = 10230
ID: 2 Money = 50170
Il s'agit d'éliminer le XML et d'utiliser des annotations pour le faire, qui est de remplacer la configuration dans le XML précédent par l'annotation @transactionnelle.
un. Mise en œuvre
@RepositoryPublic Class AnnodeMo4 {@Autowired Private Moneydao Moneydao; / ** * Transfert * * @param inuserid * @param ouserured * @param paymoney * @param status 0 indique un transfert normal, 1 indique qu'une exception est lancée en interne, 2 indique un nouveau thread, modifier l'argent d'Inuserid + 200, 3 indique un nouveau thread, modifier l'argent de l'isolation de la transaction: Problème de transaction INUSERID. En lecture seule * RollbackFor: Quelles exceptions se sont produites Norollbackfor: Quelles exceptions se sont produites pour ne pas faire de rollback * rollbackForClassName Rollback selon le nom de classe d'exception * / @transactional (propagation = propagation.Requured, isolation = isolation.default, readonly = false) public transform (final int inusery MoneyDao.QueryMoney (OutUserrid); if (entity.getMoney ()> PayMoney) {// Vous pouvez transférer de l'argent // réduire l'argent d'abord Moneydao.incrementMoney (OutUserrid, -PayMoney); TestCase (inUserrid, ouserUserid, statut); // ajouter de l'argent à Moneydao.incrementMoney (inUserId, PayMoney); System.out.println ("Le transfert est terminé! Now:" + System.Currenttimemillis ()); }} private void TestCase (final int inUserId, final int ouserUsid, final int status) {if (status == 1) {lancez new illégalargumentException ("transfert exception !!!"); } else if (status == 2) {addMoney (inUserId); essayez {thread.sleep (3000); } catch (InterruptedException e) {e.printStackTrace (); }} else if (status == 3) {addMoney (ouUserid); essayez {thread.sleep (3000); } catch (InterruptedException e) {e.printStackTrace (); }}} private void addmoney (final int userId) {System.out.println ("Inside Add Money:" + System.currentTimemillis ()); Nouveau thread (new Runnable () {public void run () {MoneyDao.inCrementMoney (Userid, 200); System.out.println ("sub modificateur Success! Now:" + System.Currenttimemillis ());}}). start (); }}Par conséquent, il est nécessaire de le configurer dans XML pour permettre l'annotation des choses
<! - Programmation des choses -> <bean id = "TransactionManager"> <propriété name = "dataSource" ref = "dataSource" /> </ank> <tx: annotation-axé transaction-manager = "transactionmanager" />
Cela le rend plus clair. Dans les projets réels, les méthodes de XML et d'annotation sont également les scénarios les plus couramment utilisés.
né Bilan de test
C'est exactement la même chose que le troisième cas de test, et le résultat de sortie est le même, et il est omis directement
Ce qui précède parle de quatre façons d'utiliser les choses au printemps. Parmi eux, la méthode du code dur peut être la meilleure compréhension, ce qui équivaut à traduire directement la méthode d'utilisation des choses en SQL dans le code Java correspondant; Et la méthode Factorybean équivaut à traiter les situations spéciales et à traiter chaque chose avec une classe de procuration pour améliorer la fonction des choses; Les deux derniers principes sont presque mis en œuvre à l'aide de la notification Thing (AOP) pour définir des points tangents et des informations connexes.
Programmation:
transactionTemplate#executeProxy Beanfactory:
Configuration XML:
Méthode d'annotation:
tx:annotation-driven transaction-manager="transactionManager"/>document
Quatre façons de gestion des transactions de printemps
Code source
Ce qui précède est l'intégralité du contenu de cet article. J'espère que le contenu de cet article a une certaine valeur de référence pour l'étude ou le travail de chacun. Si vous avez des questions, vous pouvez laisser un message pour communiquer. Merci pour votre soutien à wulin.com.