Spring plurality of data sources, and the dynamic switching (reproduced)

1. Configure two different data sources, as follows

<!-- 数据源配置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>
<!-- 监控数据库 -->
<property name="proxyFilters">
<list>
<ref bean="log-filter" />
</list> 
</property>

</bean>

<!-- 数据源配置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>
<!-- 监控数据库 -->
<property name="proxyFilters">
<list>
<ref bean="log-filter" />
</list> 
</property>

</bean>

2. The definition of a class that inherits AbstractRoutingDataSource determineCurrentLookupKey implemented method, which can realize dynamic switching databases, as follows:

public class DynamicDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
return DataSourceContextHolder.getDataSourceType();
}
}

3. Define a class variable to set the current tool thread, provided for the corresponding data source name:

{class DataSourceContextHolder public
Private static Final the ThreadLocal <String> = new new ContextHolder the ThreadLocal <String> ();
/ **
* @Description: Set data source type
* @param dataSourceType database type
* @return void
* @throws
* /
public static void setDataSourceType (String the DataSourceType) {
contextHolder.set (the DataSourceType);
}

/ **
* @Description: acquiring 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();
}
}

Then in the spring configuration, as follows:

<!-- 编写spring 配置文件的配置多数源映射关系 -->
<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>

Such configuration corresponding to two data sources and key respectively testDataSource1 testDataSource2, default database is testDataSource.
4. After the step, if no transaction management database, dynamic switching may be achieved already in the database. But if it comes to transaction management database, you need to switch to open the database in the database transaction,

Otherwise switch databases can only take effect when the next database operation. Aop can define a category of handover processing database before the transaction database open, as follows:

public class DataSourceAspect implements MethodBeforeAdvice,AfterReturningAdvice 
{

@Override
public void afterReturning(Object returnValue, Method method,
Object[] args, Object target) throws Throwable {
// TODO Auto-generated method stub
DataSourceContextHolder.clearDataSourceType();
}

@Override
public void before(Method 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 database transaction database section and a switching section sequentially, 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>

Aop using sequential execution order attribute set, dynamic switching achieved with a spring transaction management database.

Transfer: https://www.cnblogs.com/austinspark-jessylu/p/7676190.html

Guess you like

Origin www.cnblogs.com/nietzsche2019/p/11287748.html