Dynamically add data sources to switch databases based on user logins. Programmatic spring transactions.

Source: Internet
Author: User
Tags throwable

With spring data source routing, it seems that there is no way to add data sources directly, but only with reflection.

Add user data source in spring Security userdetailservice.loaduserbyusername when user login is successful

/* *             * Add user data source              *             /Routingdatasource.adddatasource (userid);

    /** * Create data sources based on user*/     Public voidAddDatasource (String userid) {if(Stringutils.isblank (userid))return; DbInfo DbInfo=Getdbinfoservice (). Getdbinfobyuserid (userid); Try{Field targetdatasources= Abstractroutingdatasource.class. Getdeclaredfield ("targetdatasources"); Field resolveddatasources= Abstractroutingdatasource.class. Getdeclaredfield ("resolveddatasources"); Targetdatasources.setaccessible (true); Resolveddatasources.setaccessible (true); Map<object, object> datasources = (map<object, object>) targetdatasources.Get( This); if(datasources.Get(Userinfo.getid (). toString ())! =NULL)                return; Map<object, datasource> dataSources2 = (map<object, datasource>) resolveddatasources.Get( This); Druiddatasource DDS=NewDruiddatasource (); Dds.seturl ("jdbc:mysql://"+ dbinfo.getdbaddr () +":"+ dbinfo.getdbport () +"/"+ dbinfo.getdbname () +"?useunicode=true&characterencoding=utf-8&zerodatetimebehavior=converttonull& Transformedbitisboolean=true&usessl=true");            Dds.setusername (Dbinfo.getusername ());            Dds.setpassword (Dbinfo.getpwd ());            Datasources.put (UserID, DDS);        Datasources2.put (UserID, DDS); } Catch(nosuchfieldexception e) {e.printstacktrace (); } Catch(illegalaccessexception e) {e.printstacktrace (); }    }

Added the data source, of course, need to delete, can be in the session listener, destroy the session when deleted

    /*** Delete data source based on user*/     Public voidRemovedatasource (String userid) {if(Stringutils.isblank (userid))return; Try{Field targetdatasources= Abstractroutingdatasource.class. Getdeclaredfield ("Targetdatasources"); Field resolveddatasources= Abstractroutingdatasource.class. Getdeclaredfield ("Resolveddatasources"); Targetdatasources.setaccessible (true); Resolveddatasources.setaccessible (true); Map<object, object> datasources = (map<object, object>) Targetdatasources.get ( This); if(Datasources.get (Userinfo.getusrno ())! =NULL) {Map<object, datasource> dataSources2 = (map<object, datasource>) Resolveddatasources.get ( This);                Datasources.remove (userid);            Datasources2.remove (userid); }        } Catch(nosuchfieldexception e) {e.printstacktrace (); } Catch(illegalaccessexception e) {e.printstacktrace (); }    }

Annotation plus AOP Toggle data source

Annotations

/***/@Target (Elementtype.method) @Retention (retentionpolicy.runtime)public @Interface  switchdatasource {}

Spring AOP, the new version of SPRINGAOP can be a good way to cut into the listener, because the listener can be managed by the spring container, in disguise to strengthen the SPRINGAOP, so that no need to use the native ASPECTJ

/*** Created by IS on 2017-4-27.*/@Component @aspect@order (0)//When configuring Spring annotation transactions, switch the data source before the transaction Public classSWITCHDATASOURCEASPECTJ {//Defining Pointcuts@Pointcut ("@annotation (Com.lzw.common.annotation.SwitchDataSource)")     Public voidSwitchdatasource () {} @Around ("Switchdatasource ()")     PublicObject Arounduserdatasource (proceedingjoinpoint joinpoint) {datasourcecontextholder.user (); Try {            returnjoinpoint.proceed (); } Catch(Throwable throwable) {throwable.printstacktrace (); }finally{datasourcecontextholder.write (); }        return NULL; }}

This allows you to add a callout switch data source on a method ( note the order of annotations for transactions and switching data sources ), but if you need to switch to a different data source to query the data multiple times in one method, you will consume many connections, in order to better control the number of database connections, you need to use spring transaction

Programmatic Spring transactions

Inject TransactionManager

    @Resource    private Platformtransactionmanager Platformtransactionmanager;

Start transaction, open transaction is for database connection reuse, individual database per user, access is not large, so no connection pool is configured

     //to save the number of connections, try to get the required data in one switchDatasourcecontextholder.user (); //Transactiontemplate must come out every time, cannot use Spring Singleton injection, the set of data will always exist.Transactiontemplate transactiontemplate =Newtransactiontemplate (Platformtransactionmanager);        Transactiontemplate.setpropagationbehavior (Propagation.REQUIRES_NEW.value ()); Transactiontemplate.execute (NewTransactioncallbackwithoutresult () {@Override Public voidDointransactionwithoutresult (transactionstatus status) {//Database Operation code            }        }); Datasourcecontextholder.write ();

  

Dynamically add data sources to switch databases based on user logins. Programmatic spring transactions.

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.