Dynamic invocation and transaction processing based on spring multi-data source

Source: Internet
Author: User
Tags throwable

Demand:

There are times when we need to connect to multiple databases, but we don't know exactly which to call before the method call. That is, the connection of multiple databases is maintained at the same time, determined according to the parameters passed in the method.

Single data source invocation and the process of dynamic invocation of multiple data sources, it can be seen in the DAO layer that a DataSource selector is needed to determine exactly which data source to invoke.

Implementation method

Provides a common parent class for the DAO layer, maintaining a connection to multiple data sources (I am based on Ibatis, that is, maintaining multiple sqlsessiontemplate)

/** * Created by Hzlizhou on 2017/2/6. */public Abstract class Multidatasourcedao implements Idaosupport {private map<string, sqlsessiontemplate> Sqlse    Ssiontemplatemap;    Private Multidatasourceselector Multidatasourceselector; Public Multidatasourcedao (map<string, sqlsessiontemplate> Sqlsessiontemplatemap, Multidatasourceselector        Multidatasourceselector) {this.sqlsessiontemplatemap = Sqlsessiontemplatemap;    This.multidatasourceselector = Multidatasourceselector;    } public map<string, Sqlsessiontemplate> Getsqlsessiontemplatemap () {return sqlsessiontemplatemap; } public void Setsqlsessiontemplatemap (map<string, sqlsessiontemplate> sqlsessiontemplatemap) {this.sqlSe    Ssiontemplatemap = Sqlsessiontemplatemap; }//subclasses dynamically acquire Sqlsessiontemplate protected sqlsessiontemplate getsqlsessiontemplate () {String clustername by this method        = Multidatasourceselector.getname (); Sqlsessiontemplate result = SqlsessiontemplAtemap.get (clustername);        Assert.notnull (result);    return result;  }}

Multidatasourceselector is an excuse, depending on the current calling environment, to return different parameters, according to which you can determine which sqlsessiontemplate to use, for example, I put the current environment into the threadlocal

Public interface Multidatasourceselector {    String getName ();} public class Dubbocontextdatasourceselector implements Multidatasourceselector {    private String defaultname;    Public Dubbocontextdatasourceselector (String defaultname) {        this.defaultname = defaultname;    }    @Override public    String GetName () {        //dubbocontextholder is a map that maintains a threadlocal        string res = Dubbocontextholder.getcontext (). get (Dubbocontextconstants.cluster_name);        if (res = = null) {            res = getdefaultname ();        }        return res;    }    Public String Getdefaultname () {        return defaultname;    }}

Then it is dynamic to get sqlsessiontemplate in the DAO layer.

Dynamic transactions

In fact, this is good to do, and then we face a slightly more complex problem, that DataSource is dynamic, the transaction must be dynamic. And there is no intrusion into the original code (such as the @transactional annotation in spring), then implement a method similar to @transactional. Names are called @dynamictransactional.

@Documented @target ({METHOD, TYPE}) @Retention (RUNTIME) public @interface dynamictransactional {    propagation Propagation () default propagation.required;    class<? Extends throwable>[] Rollbackfor () default {};}

  

The basic idea is to intercept @dynamictransactional annotations through AOP slices, invoke them, and then programmatically implement the transaction

The core method in the plane is

Private Object invokewithintransaction (final proceedingjoinpoint PJP, final dynamictransactional dynamictransaction) { Create Transactiontemplate final Platformtransactionmanager tran = Multitransactionmanagerholder.gettransactionmanager    ();    Transactiontemplate transactiontemplate = new Transactiontemplate ();    Transactiontemplate.setpropagationbehavior (Dynamictransaction.propagation (). value ());    Transactiontemplate.settransactionmanager (Tran); Execution of Return Transactiontemplate.execute (new transactioncallback<object> () {@Override public Ob in a transaction            Ject dointransaction (transactionstatus status) {Object result = null;            try {result = Pjp.proceed ();                } catch (Throwable throwable) {class<? extends throwable>[] C = dynamictransaction.rollbackfor (); for (class< extends throwable> tmp:c) {if (Tmp.isassignablefrom (THROWABLE.GETCL                 ()) {       Status.setrollbackonly ();        }}} return result; }    });}

  

Where Multitransactionmanagerholder and the above Dynamic Data source selection principle, by taking the variable from the threadlocal, select the corresponding TransactionManager return

Configuration of Facets: The focus is on how to slice the specified annotations

<aop:config>

<aop:aspect id= "Multitransactionmanageraspect" ref= "MULTITRANSACTIONMANAGERAOP" >

<aop:around method= "Invokewithintransaction"

Arg-names= "Dynamictransaction"

Pointcut= "@annotation (dynamictransaction)"/>

</aop:aspect>

</aop:config>

Of course, this only implements the @dynamictransactional usage on the method, if the annotation is also used on the class, add a pointcut to all functions, and determine if there are @dynamictransactional annotations on the class of the Pointcut

Note: Due to the priority of the tangent plane, a little bit of processing is needed if the annotation on the implementation method takes precedence over the class.

Call time series diagram

Its own implementation is based on Abstractroutingdatasource, adding multiple DataSource to Sqlsessionfactory, as in the previous way, by Threadlocal to determine which datasource to use.

On dynamic transactions, the above is the use of slices, custom tags, using transactiontemplate to achieve, if you want more elegant, you can imitate Datasourcetransactionmanager write a,

Dynamic invocation and transaction processing based on spring multi-data source

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.