1. Configure two different data sources, as follows
<!--data Source configuration 1--
<bean id= "TestDataSource1" class= "Com.alibaba.druid.pool.DruidDataSource" init-method= "Init" destroy-method= " Close ">
<property name= "Driverclassname" value= "${db.driver}"/>
<property name= "url" value= "${unity.db.jdbc.url}"/>
<property name= "username" value= "${db.login.name}" ></property>
<property name= "Password" value= "${db.login.password}"/>
<property name= "Filters" value= "${db.filters}" ></property>
<property name= "maxactive" value= "${db.pool.maxactive}" ></property>
<property name= "InitialSize" value= "${db.pool.initialsize}" ></property>
<property name= "Minidle" value= "${db.pool.minidle}" ></property>
<property name= "maxwait" value= "${db.maxwait}" ></property>
<property name= "Timebetweenevictionrunsmillis" value= "${db.timebetweenevictionrunsmillis}" ></property >
<property name= "Minevictableidletimemillis" value= "${db.minevictableidletimemillis}" ></property>
<property name= "Validationquery" value= "${db.validationquery}" ></property>
<property name= "Testwhileidle" value= "${db.testwhileidle}" ></property>
<property name= "Testonborrow" value= "${db.testonborrow}" ></property>
<property name= "Testonreturn" value= "${db.testonreturn}" ></property>
<property name= "poolpreparedstatements" value= "${db.poolpreparedstatements}" ></property>
<property name= "maxopenpreparedstatements" value= "${db.maxopenpreparedstatements}" ></property>
<!--monitoring database--
<property name= "Proxyfilters" >
<list>
<ref bean= "Log-filter"/>
</list>
</property>
</bean>
<!--data Source Configuration 2--
<bean id= "TestDataSource2" class= "Com.alibaba.druid.pool.DruidDataSource" init-method= "Init" destroy-method= " Close ">
<property name= "Driverclassname" value= "${db.driver}"/>
<property name= "url" value= "${pub.db.jdbc.url}"/>
<property name= "username" value= "${db.login.name}" ></property>
<property name= "Password" value= "${db.login.password}"/>
<property name= "Filters" value= "${db.filters}" ></property>
<property name= "maxactive" value= "${db.pool.maxactive}" ></property>
<property name= "InitialSize" value= "${db.pool.initialsize}" ></property>
<property name= "Minidle" value= "${db.pool.minidle}" ></property>
<property name= "maxwait" value= "${db.maxwait}" ></property>
<property name= "Timebetweenevictionrunsmillis" value= "${db.timebetweenevictionrunsmillis}" ></property >
<property name= "Minevictableidletimemillis" value= "${db.minevictableidletimemillis}" ></property>
<property name= "Validationquery" value= "${db.validationquery}" ></property>
<property name= "Testwhileidle" value= "${db.testwhileidle}" ></property>
<property name= "Testonborrow" value= "${db.testonborrow}" ></property>
<property name= "Testonreturn" value= "${db.testonreturn}" ></property>
<property name= "poolpreparedstatements" value= "${db.poolpreparedstatements}" ></property>
<property name= "maxopenpreparedstatements" value= "${db.maxopenpreparedstatements}" ></property>
<!--monitoring database--
<property name= "Proxyfilters" >
<list>
<ref bean= "Log-filter"/>
</list>
</property>
</bean>
2. Define a class inheritance Abstractroutingdatasource implementation Determinecurrentlookupkey method, this method can realize the dynamic switch of the database, as follows:
public class Dynamicdatasource extends Abstractroutingdatasource {
@Override
Protected Object Determinecurrentlookupkey () {
return Datasourcecontextholder.getdatasourcetype ();
}
}
3. Define a tool class that can set variables for the current thread to set the corresponding data source name:
public class Datasourcecontextholder {
private static final threadlocal<string> Contextholder = new threadlocal<string> ();
/**
* @Description: Set the data source type
* @param datasourcetype Database type
* @return void
* @throws
*/
public static void Setdatasourcetype (String datasourcetype) {
Contextholder.set (DatasourceType);
}
/**
* @Description: Get data Source Type
* @param
* @return String
* @throws
*/
public static String Getdatasourcetype () {
return Contextholder.get ();
}
/**
* @Description: Clear Data Source Type
* @param
* @return void
* @throws
*/
public static void Cleardatasourcetype () {
Contextholder.remove ();
}
}
It is then configured in spring as follows:
<!--to write a spring configuration file configuration Most source mapping relationships-
<bean class= "Com.sino.access.database.DynamicDataSource" id= "DataSource" >
<property name= "Targetdatasources" >
<map key-type= "Java.lang.String" >
<entry value-ref= "TestDataSource1" key= "<span style=" font-family:arial, Helvetica, Sans-serif; " >testdatasource1</span><span style= "font-family:arial, Helvetica, Sans-serif;" > "></entry></span>
<entry value-ref= "TestDataSource2" key= "TestDataSource2" ></entry>
</map>
</property>
<property name= "Defaulttargetdatasource" ref= "TestDataSource1" >
</property>
</bean>
This configures two data sources corresponding to the key TestDataSource1 and TestDataSource2 respectively, the default database is Testdatasource.
4. After completing the above steps, if there is no transaction management of the database, the dynamic switch of the database can be realized . However, if the transaction management of the database is involved, the database transaction must be switched on .
Otherwise, the database switchover will only take effect the next time the database operation occurs. You can define an AOP processing class to switch databases before the database transaction is opened, as follows:
public class Datasourceaspect implements Methodbeforeadvice,afterreturningadvice
{
@Override
public void afterreturning (Object returnvalue, method,
Object[] args, Object target) throws Throwable {
TODO auto-generated Method Stub
Datasourcecontextholder.cleardatasourcetype ();
}
@Override
public void before (method, object[] args, Object target)
Throws Throwable {
if (Method.isannotationpresent (Datasource.class))
{
DataSource DataSource = method.getannotation (Datasource.class);
Datasourcecontextholder.setdatasourcetype (Datasource.name ());
}
Else
{
Datasourcecontextholder.setdatasourcetype (SinoConstant.DataSourceType.unityDataSource.toString ());
}
}
}
5. Set the database transaction facets and the order in which the database slices are executed, as follows:
<aop:config>
<aop:pointcut id= "transactionpointcut" expression= "Execution (* com.test.service.*.* (..))"/>
<aop:advisor pointcut-ref= "Transactionpointcut"
advice-ref= "Txadvice" order= "2"/>
<aop:advisor advice-ref= "Datasourceexchange" pointcut-ref= "Transactionpointcut" order= "1"/>
</aop:config>
Use the Order property of AOP to set the sequence of execution so that the spring database dynamic switchover with transaction management is implemented.
Spring configures multiple data sources and enables dynamic switching