Implementing multi-data source transaction management in spring

Source: Internet
Author: User

Implementing multi-data source transaction management in spring Preface

Since multiple data sources are introduced in the project and there is a need to write to multiple data sources, transaction management of multiple data sources is naturally an unavoidable problem, which gives me a @Transactional further understanding of the annotations (but not really in depth).

However, this is an evolutionary process, the beginning of the project did not use the @Transactional specified specific TransactionManager , so the new data source, the original transaction has an impact, which is occasionally in a test error and results did not rollback after the discovery, and then for @Transactional the annotations of some parameter items are understood.

Research

Since there are two containers in the container TransactionManager , then the @Transactional annotated method is used TransactionManager to manage the transaction, or the use of two at the same time for TransactionManager transaction management is a problem we need to figure out.
First, let's see if @Transactional there are any configuration items on the annotations to specify, sure enough TransactionManager , the discovery value attribute is used to specify TransactionManager the specific, through id or name to specify the only one TransactionManager , The problem is much simpler for a method that requires only one transaction management:

    @Transactional(value"database2TransactionManager")    publicvoidtest(String a) {        // business operation    }

About which TransactionManager will be used when TransactionManager is not specified, interested children's shoes can refer to another article, speaking more clearly: Http://blog.sina.com.cn/s/blog_ 8f61307b0100ynfb.html

Well, back to the question we're studying, what about business methods that need to write to multiple data sources?

further study

It @Transactional does not seem to provide such a function, then you write a bar. I remember the transaction management of Spring in the sub-programming transaction and the declarative transaction. We usually use @Transactional declarative transactions, the benefits of which are actually more flexible, the code is less coupled, the final transaction management implementation is the same, but the specific logic is stripped into the plane. So we can write a "programmatic transaction" by hand-writing a slice, which is, of course, declarative when used in a specific application.

General programmatic transaction notation in Java:

 Public  class Userserviceimpl implements userservice {    @Resource    PrivateTransactionManager Txmanager;@Resource    PrivateUserdao Userdao;@Resource    PrivateAddressdao Addressdao; Public Boolean Saveuser(User user) {Transactiondefinition txdefinition =NewTransactiondefinition (); Transactionstatus txstatus = txmanager.gettransaction (txdefinition);Booleanresult =false;Try{result = Userdao.save (user);if(!result) {return false;            } result = Addressdao.save (User.getid (), user.getaddress ());        Txmanager.commit (Txstatus); }Catch(Exception e) {result =false;        Txmanager.rollback (Txstatus); }returnResult }}

We use this logic to extract the transaction management correlation into the tangent plane, and before entering the target method, let more than one TransactionManager open the transaction, and after the successful execution together or fail after the rollback, the specific code:

/** * @author Zhu * @date 2015-7-15 * @version 0.0.1 * @description  * * Public  class multitransactionalaspect {    PrivateLogger Logger = Loggerfactory.getlogger (GetClass ()); PublicObjectaround(Proceedingjoinpoint PJP, multitransactional multitransactional)throwsthrowable {stack<datasourcetransactionmanager> Datasourcetransactionmanagerstack =NewStack<datasourcetransactionmanager> (); Stack<transactionstatus> Transactionstatustack =NewStack<transactionstatus> ();Try{if(!opentransaction (Datasourcetransactionmanagerstack, Transactionstatustack, multitransactional)) {return NULL;            } Object ret = Pjp.proceed (); Commit (Datasourcetransactionmanagerstack, transactionstatustack);returnRet }Catch(Throwable e)            {rollback (datasourcetransactionmanagerstack, transactionstatustack); Logger.error (String.Format ("Multitransactionalaspect, method:%s-%s occors error:", PJP. Gettarget (). GetClass (). Getsimplename (), PJP. Getsignature (). g Etname ()), e);ThrowE }    }/** * @author Zhu * @date 2015-7-25 pm 7:55:46 * @description * @param  datasourcetransactionmanagerstack * @param transactionstatustack * @param Values * *    Private Boolean opentransaction(Stack<datasourcetransactionmanager> Datasourcetransactionmanagerstack, stack<transactions Tatus> Transactionstatustack, multitransactional multitransactional) {string[] Transactionmangername s = multitransactional.values ();if(Arrayutils.isempty (Multitransactional.values ())) {return false; } for(String beanname:transactionmangernames)                    {Datasourcetransactionmanager Datasourcetransactionmanager = (datasourcetransactionmanager) ContextHolder            . Getbean (Beanname); Transactionstatus transactionstatus = Datasourcetransactionmanager. Gettransaction (NewDefaulttransactiondefinition ());            Transactionstatustack.push (Transactionstatus);        Datasourcetransactionmanagerstack. push (Datasourcetransactionmanager); }return true; }/** * @author Zhu * @date 2015-7-25 pm 7:56:39 * @description * @param  datasourcetransactionmanagerstack * @param transactionstatustack * *    Private void Commit(Stack<datasourcetransactionmanager> Datasourcetransactionmanagerstack, stack<transactions Tatus> transactionstatustack) { while(!datasourcetransactionmanagerstack.isempty ())        {Datasourcetransactionmanagerstack.pop (). Commit (Transactionstatustack.pop ()); }    }/** * @author Zhu * @date 2015-7-25 pm 7:56:42 * @description * @param  datasourcetransactionmanagerstack * @param transactionstatustack * *    Private void rollback(Stack<datasourcetransactionmanager> Datasourcetransactionmanagerstack, stack<transactions Tatus> transactionstatustack) { while(!datasourcetransactionmanagerstack.isempty ())        {Datasourcetransactionmanagerstack.pop (). Rollback (Transactionstatustack.pop ()); }    }

The overall structure is clear:
1. First of all, according to the specified number of TransactionManager open transactions, this order does not affect, because in fact, everyone is equal.
2. The next step is to invoke the target method to execute the specific business logic
3. If the return is successful, each transaction is submitted, and if the error is dropped, then each transaction is rolled back

Why do you use Stack it to TransactionManager save TransactionStatus and? That's because Spring 's transactions are done in the lifo/stack behavior Way. If the order is incorrect, the error will be:

java.lang.IllegalStateException:Cannot deactivate transaction synchronization-not active at org. Springframework. Transaction. Support. Transactionsynchronizationmanager. Clearsynchronization(Transactionsynchronizationmanager. Java:313) at Org. Springframework. Transaction. Support. Transactionsynchronizationmanager. Clear(Transactionsynchronizationmanager. Java:451) at Org. Springframework. Transaction. Support. Abstractplatformtransactionmanager. Cleanupaftercompletion(Abstractplatformtransactionmanager. Java:986) at Org. Springframework. Transaction. Support. Abstractplatformtransactionmanager. Processcommit(Abstractplatformtransactionmanager. Java:782) at Org. Springframework. Transaction. Support. Abstractplatformtransactionmanager. Commit(Abstractplatformtransactio
Off Topic

Beginning to encounter this problem, the first thought is distributed transaction management, but also to see the JTA related articles, but it seems to be more troublesome, and are some old articles, so want to try their own implementation, and finally realized. So you want to know JTA TransactionManager what's the use of it?

Copyright NOTICE: This article for Bo Master original article, without Bo Master permission not reproduced.

Implementing multi-data source transaction management in spring

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.