Spring+MyBatis多数据源配置实现

在开发项目时,有多数据源的需求。在网上查阅资料后,实现了。由于本人经验不足,且需求本身要求不高,所以采用手动控制,非自动切换。

概览

img

使用技术

IOC容器:Spring

Web框架:SpringMVC

ORM框架:Mybatis

文件

注意,以下改动是基于单数据源实现成功后。

  1. Spring 容器(XML)

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xmlns:context="http://www.springframework.org/schema/context"
          xmlns:aop="http://www.springframework.org/schema/aop"
          xmlns:tx="http://www.springframework.org/schema/tx"
          xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop.xsd
    http://www.springframework.org/schema/tx
    http://www.springframework.org/schema/tx/spring-tx.xsd">
    
       <!--加载数据库配置文件-->
       <context:property-placeholder location="classpath:jdbc.properties"/>
    
       <!-- ===============第一个数据源MySQL的配置=============== -->
       <!--配置数据源 c3p0 连接池-->
       <bean id="dataSource2MySQL" class="com.mchange.v2.c3p0.ComboPooledDataSource" >
           <property name="driverClass" value="${jdbc.mysql.driver}"/>
           <property name="jdbcUrl" value="${jdbc.mysql.url}"/>
           <property name="user" value="${jdbc.mysql.username}"/>
           <property name="password" value="${jdbc.mysql.password}"/>
           <!--以下皆为连接池参数,依实际情况配置-->
           <property name="maxPoolSize" value="200"/>
           <property name="minPoolSize" value="10"/>
           <!--初始化时获取的连接数,取值应在minPoolSize与maxPoolSize之间。Default: 3 -->
           <property name="initialPoolSize" value="10"/>
           <property name="checkoutTimeout" value="60"/>
           <property name="unreturnedConnectionTimeout" value="25"/>
           <property name="maxIdleTimeExcessConnections" value="20"/>
           <property name="maxConnectionAge" value="20"/>
           <property name="idleConnectionTestPeriod" value="50"/>
           <property name="maxStatements" value="0"/>
    
       </bean>
    
       <!-- ===============第二个数据源SQLServer的配置=============== -->
    
       <!--配置数据源 c3p0 连接池-->
       <bean id="dataSource2SQLServer" class="com.mchange.v2.c3p0.ComboPooledDataSource" >
           <property name="driverClass" value="${jdbc.sqlserver.driver}"/>
           <property name="jdbcUrl" value="${jdbc.sqlserver.url}"/>
           <property name="user" value="${jdbc.sqlserver.username}"/>
           <property name="password" value="${jdbc.sqlserver.password}"/>
           <!--以下皆为连接池参数,依实际情况配置-->
           <property name="maxPoolSize" value="200"/>
           <!--初始化时获取的连接数,取值应在minPoolSize与maxPoolSize之间。Default: 3 -->
           <property name="initialPoolSize" value="10"/>
           <property name="minPoolSize" value="10"/>
           <property name="checkoutTimeout" value="60"/>
           <property name="unreturnedConnectionTimeout" value="25"/>
           <property name="maxIdleTimeExcessConnections" value="20"/>
           <property name="maxConnectionAge" value="20"/>
           <property name="idleConnectionTestPeriod" value="50"/>
           <property name="maxStatements" value="0"/>
       </bean>
    
       <!--将DynamicDataSource Bean加入到Spring的上下文xml配置文件中去,同时配置DynamicDataSource的targetDataSources(多数据源目标)属性的Map映射。-->
    
       <bean id="dataSource" class="com.system.util.DynamicDataSource">
           <property name="targetDataSources">
               <map key-type="java.lang.String">
                   <entry key="dataSource2MySQL" value-ref="dataSource2MySQL"/>
                   <entry key="dataSource2SQLServer"  value-ref="dataSource2SQLServer" />
               </map>
           </property>
           <property name="defaultTargetDataSource" ref="dataSource2MySQL"/>
       </bean>
    
       <!--配置SqlSessionFactory-->
       <bean id="sessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
           <!--加载mybatis配置文件-->
           <property name="configLocation" value="classpath:mybatis/mybatis.cfg.xml"/>
           <!--数据源-->
           <property name="dataSource" ref="dataSource"/>
       </bean>
    
       <!--Mapper批量扫描,从Mapper包扫描接口,自动创建代理对象,并在Spring容器中自动注册
       使用 Mybatis与Spring整合包的这个 Mapper 扫描器后, Mybatis 配置文件里的扫描器,就可以取消掉了
       遵循的规范 不变
       自动扫描出来的Mapper的bean的id为Mapper类名(首字母小写)
       -->
       <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
           <!--如果需要扫描多个报下的mapper,每个包中间使用半角逗号分开-->
           <property name="basePackage" value="com.system.mapper"/>
           <property name="sqlSessionFactoryBeanName" value="sessionFactory"/>
       </bean>
    </beans>

    在 Spring 容器中配置两个数据源。

  2. CustomerContextHolder

    public class CustomerContextHolder {
       //MySQL
       public static final String DATA_SOURCE_MYSQL = "dataSource2MySQL";
       //SQLServer
       public static final String DATA_SOURCE_MSSQL = "dataSource2SQLServer";
       //用ThreadLocal来设置当前线程使用哪个dataSource
       private static final ThreadLocal<String> contextHolder = new ThreadLocal<String>();
       public static void setCustomerType(String customerType) {
           contextHolder.set(customerType);
       }
       public static String getCustomerType() {
           String dataSource = contextHolder.get();
           if (StringUtils.isEmpty(dataSource)) {
               return DATA_SOURCE_MYSQL;
           }else {
               return dataSource;
           }
       }
       public static void clearCustomerType() {
           contextHolder.remove();
       }
    }

    获得和设置上下文环境,为一线程安全的 ThreadLocal 。

  3. DynamicDataSource

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

    DynamicDataSource 动态数据源类,扩展 Spring 的 AbstractRoutingDataSource 抽象类,实现动态数据源, AbstractRoutingDataSource 中的抽象方法 determineCurrentLookupKey 是实现数据源的 route 的核心.这里对该方法进行 Override 。

使用

   //切换数据源至SQLServer
   CustomerContextHolder.setCustomerType(CustomerContextHolder.DATA_SOURCE_MSSQL);
   //切换数据源至MySQL
   CustomerContextHolder.setCustomerType(CustomerContextHolder.DATA_SOURCE_MYSQL);
posted @ 2018-03-02 09:50  夏洛克卷  阅读(61)  评论(0编辑  收藏  举报