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

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

<!-- 数据源配置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.定义一个类继承AbstractRoutingDataSource实现determineCurrentLookupKey方法,该方法可以实现数据库的动态切换,如下:

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

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

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中配置,如下:

 <!-- 编写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处理类在数据库事务开启之前切换数据库,如下:

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.设置数据库事务切面和切换数据库切面执行的顺序,如下:

<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数据库动态切换。

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

(0)

相关推荐

  • Spring整合多数据源实现动态切换的实例讲解

    在实际项目中时常需要连接多个数据库,而且不同的业务需求在实现过程当中往往需要访问不同的数据库. jdbc.properties配置文件,配置多个dataSource ##########################MySQL##################################### hibernate.dialect=org.hibernate.dialect.MySQLInnoDBDialect connection.driver_class=com.mysql.jdbc.

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

    1.配置两个不同的数据源,如下(由于项目使用的是druid数据库连接,配置可以会复杂点比较): <!-- 数据源配置1 --> <bean id="testDataSource1" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close"> <property name=&quo

  • js、jquery图片动画、动态切换示例代码

    复制代码 代码如下: <style type="text/css"> #banner { padding: 5px; position: relative; width: 968px; height: 293px; /*border: 1px solid #666;*/ overflow: hidden; font-size: 16px; } #banner_list img { border: 0px; } #banner_bg { margin-bottom: 5px;

  • Spring+Mybatis动态切换数据源的方法

    功能需求是公司要做一个大的运营平台: 1.运营平台有自身的数据库,维护用户.角色.菜单.部分以及权限等基本功能. 2.运营平台还需要提供其他不同服务(服务A,服务B)的后台运营,服务A.服务B的数据库是独立的. 所以,运营平台至少要连三个库:运营库,A库,B库,并且希望达到针对每个功能请求能够自动切换到对应的数据源(我最终实现是针对Service的方法级别进行切换的,也可以实现针对每个DAO层的方法进行切换.我们系统的功能是相互之间比较独立的). 第一步:配置多数据源 1.定义数据源: 我采用的

  • druid多数据源配置+Datasurce动态切换方式

    目录 druid多数据源配置+Datasurce动态切换 AbstractRoutingDataSource 数据源动态切换 例子 配置多数据源并实现Druid自动切换 配置yml文件 主数据源配置 从数据源配置 使用dao 日志 druid多数据源配置+Datasurce动态切换 AbstractRoutingDataSource 数据源动态切换 spring 使用AbstractRoutingDataSource自定义动态数据源时的事务处理, 需要继承spring的AbstractRouti

  • Spring + Mybatis 项目实现动态切换数据源实例详解

    项目背景:项目开发中数据库使用了读写分离,所有查询语句走从库,除此之外走主库. 最简单的办法其实就是建两个包,把之前数据源那一套配置copy一份,指向另外的包,但是这样扩展很有限,所有采用下面的办法. 参考了两篇文章如下: http://www.jb51.net/article/111840.htm http://www.jb51.net/article/111842.htm 这两篇文章都对原理进行了分析,下面只写自己的实现过程其他不再叙述. 实现思路是: 第一步,实现动态切换数据源:配置两个D

  • Spring(AbstractRoutingDataSource)实现动态数据源切换示例

    一.前言 近期一项目A需实现数据同步到另一项目B数据库中,在不改变B项目的情况下,只好选择项目A中切换数据源,直接把数据写入项目B的数据库中.这种需求,在数据同步与定时任务中经常需要. 那么问题来了,该如何解决多数据源问题呢?不光是要配置多个数据源,还得能灵活动态的切换数据源.以spring+hibernate框架项目为例: 单个数据源绑定给sessionFactory,再在Dao层操作,若多个数据源的话,那不是就成了下图: 可见,sessionFactory都写死在了Dao层,若我再添加个数据

  • Spring实现动态切换多数据源的解决方案

    前言 Spring动态配置多数据源,即在大型应用中对数据进行切分,并且采用多个数据库实例进行管理,这样可以有效提高系统的水平伸缩性.而这样的方案就会不同于常见的单一数据实例的方案,这就要程序在运行时根据当时的请求及系统状态来动态的决定将数据存储在哪个数据库实例中,以及从哪个数据库提取数据. Spring2.x以后的版本中采用Proxy模式,就是我们在方案中实现一个虚拟的数据源,并且用它来封装数据源选择逻辑,这样就可以有效地将数据源选择逻辑从Client中分离出来.Client提供选择所需的上下文

  • spring boot + mybatis实现动态切换数据源实例代码

    前言 前几天有个需求,需要使用不同的数据源,例如某业务要用A数据源,另一个业务要用B数据源.我上网收集了一些资料整合了一下,虽然最后这个需求不了了之了,但是多数据源动态切换还是蛮好用的,所以记录一下,或许以后有用呢?或者自己感兴趣又想玩呢! 下面话不多说了,随着小编来一起看看详细的介绍吧 方法如下: 1.加个依赖 <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybat

  • spring实现动态切换、添加数据源及源码分析

    前言 对于数据量在1千万,单个mysql数据库就可以支持,但是如果数据量大于这个数的时候,例如1亿,那么查询的性能就会很低.此时需要对数据库做水平切分,常见的做法是按照用户的账号进行hash,然后选择对应的数据库. 最近公司项目需求,由于要兼容老系统的数据库结构,需要搭建一个 可以动态切换.添加数据源的后端服务. 参考了过去的项目,通过配置多个SqlSessionFactory 来实现多数据源,这么做的话,未免过于笨重,而且无法实现动态添加数据源这个需求 通过 spring AbstractRo

随机推荐