服务器之家

服务器之家 > 正文

Spring配置多个数据源并实现动态切换示例

时间:2020-09-07 08:58     来源/作者:gaofuqi

1.配置两个不同的数据源,如下(由于项目使用的是druid数据库连接,配置可以会复杂点比较):

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<!-- 数据源配置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>
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<!-- 数据源配置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.定义一个类继承AbstractRoutingDataSource实现determineCurrentLookupKey方法,该方法可以实现数据库的动态切换,如下:

?
1
2
3
4
5
6
public class DynamicDataSource extends AbstractRoutingDataSource {
  @Override
  protected Object determineCurrentLookupKey() {
    return DataSourceContextHolder.getDataSourceType();
  }
}

3.定义一个可以设置当前线程的变量的工具类,用于设置对应的数据源名称:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public class DataSourceContextHolder {
  private static final ThreadLocal<String> contextHolder = new ThreadLocal<String>();
  /**
   * @Description: 设置数据源类型
   * @param dataSourceType 数据库类型
   * @return void
   * @throws
   */
  public static void setDataSourceType(String dataSourceType) {
    contextHolder.set(dataSourceType);
  }
   
  /**
   * @Description: 获取数据源类型
   * @param
   * @return String
   * @throws
   */
  public static String getDataSourceType() {
    return contextHolder.get();
  }
   
  /**
   * @Description: 清除数据源类型
   * @param
   * @return void
   * @throws
   */
  public static void clearDataSourceType() {
    contextHolder.remove();
  }
}

然后在spring中配置,如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
<!-- 编写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>
 </bean>

这样配置两个数据源对应的key分别为testDataSource1和testDataSource2,默认数据库是testDataSource。

4.完成以上步骤后,如果没有数据库的事务管理,已经可以实现数据库的动态切换了。但是如果涉及到数据库的事务管理,需要在数据库事务开启切换数据库,

否则数据库的切换只能在下次数据库操作时才生效。可以定义一个aop处理类在数据库事务开启之前切换数据库,如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
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.设置数据库事务切面和切换数据库切面执行的顺序,如下:

?
1
2
3
4
5
6
<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的order属性设置执行的顺序,这样实现了带事务管理的spring数据库动态切换。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。

原文链接:http://blog.csdn.net/gaofuqi/article/details/46417281

标签:

相关文章

热门资讯

2020微信伤感网名听哭了 让对方看到心疼的伤感网名大全
2020微信伤感网名听哭了 让对方看到心疼的伤感网名大全 2019-12-26
Intellij idea2020永久破解,亲测可用!!!
Intellij idea2020永久破解,亲测可用!!! 2020-07-29
歪歪漫画vip账号共享2020_yy漫画免费账号密码共享
歪歪漫画vip账号共享2020_yy漫画免费账号密码共享 2020-04-07
最新idea2020注册码永久激活(激活到2100年)
最新idea2020注册码永久激活(激活到2100年) 2020-07-29
电视剧《琉璃》全集在线观看 琉璃美人煞1-59集免费观看地址
电视剧《琉璃》全集在线观看 琉璃美人煞1-59集免费观看地址 2020-08-12
返回顶部