您的位置:首页 > 编程语言 > Java开发

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

2016-08-11 10:43 776 查看
http://blog.csdn.net/gaofuqi/article/details/46417281

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

  

[html] view
plain copy

<!-- 数据源配置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>  

[html] view
plain copy

<!-- 数据源配置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方法,该方法可以实现数据库的动态切换,如下:

[java] view
plain copy

 





public class DynamicDataSource extends AbstractRoutingDataSource {  

    @Override  

    protected Object determineCurrentLookupKey() {  

        return DataSourceContextHolder.getDataSourceType();  

    }  

}  

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

[java] view
plain copy

 





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

[html] view
plain copy

 





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

[java] view
plain copy

 





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

[html] view
plain copy

 





<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数据库动态切换。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: