MyBatis 多數據源配置

 關於 Spring+MyBatis框架的配置這裏我就不說了,不會的同學在網上搜搜, 這篇文章主要講 多數據源的配置
我的項目環境是 spring4.3.3.RELEASE
<!-- mybatis核心包 -->
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.2.6</version>
</dependency>
<!-- mybatis/spring包 -->
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis-spring</artifactId>
    <version>1.2.2</version>
</dependency>

網上關於多數據源配置有很多方法,我在裏面挑了一個最簡單,最實用的一種,核心原理也就一句話 寫一個DynamicDataSource類來繼承AbstractRoutingDataSource,並重寫determineCurrentLookupKey()方法,來達到動態切換數據庫

1): DynamicDataSource


import java.util.logging.Logger;

import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;

/**
 * 動態切換數據庫
 * 
 * @author wangjianghai ([email protected])
 * @date 2016年11月30日 上午9:40:53
 * @Description: 繼承AbstractRoutingDataSource,並重寫determineCurrentLookupKey()方法
 */
public class DynamicDataSource extends AbstractRoutingDataSource {

    @Override
    public Logger getParentLogger() {
        return null;
    }

    @Override
    protected Object determineCurrentLookupKey() {
        return DataSourceContextHolder.getDbType();
    }

}

重寫 determineCurrentLookupKey 方法,DataSourceContextHolder.getDbType()這個框架在查詢數據的時候獲取數據源信息,看下面

2) : DataSourceContextHolder

import com.lb.utils.StringUtil;

/**
 * 數據庫切換的工具類
 * 
 * @author wangjianghai ([email protected])
 * @date 2016年11月30日 上午9:30:06
 * @Description: 注意java.lang.ThreadLocal 的使用
 */
public class DataSourceContextHolder {
    private static final ThreadLocal<String> contextHolder = new ThreadLocal<String>();


    public static void setDbType(String dbType) {
        contextHolder.set(dbType);
    }

    public static String getDbType() {
        //先判斷程序中有沒有設置數據源,如果沒有 就選擇默認的一個
        String db =((String) contextHolder.get());
        if(StringUtil.isEmpty(db)){
            setDbType(DataSourceType.SOURCE_ONE);
            db =((String) contextHolder.get());
        }
        return db;
    }

    public static void clearDbType() {
        contextHolder.remove();
    }
}

StringUtil.isEmpty(db)這判斷是判斷 db 這個字符串是否是 null or “”,

3) : DataSourceType 這個類可有可無

/**
 * 數據庫類型常量類
 * 
 * @author wangjianghai ([email protected])
 * @date 2016年11月30日 下午1:57:05
 * @Description:
 */
public class DataSourceType {

    public static final String SOURCE_ONE= "db1";

    public static final String SOURCE_TWO = "db2";

    public static final String SOURCE_ORACLE = "db_oracle";
}

4) : 接下來就是 spring-mybatis.xml 的配置了,這裏我只給出 多數據源的配置,

<bean id="db1" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">

        <!-- 數據源驅動類可不寫,Druid默認會自動根據URL識別DriverClass -->
        <property name="driverClassName" value="${db.driver}" />
        <!-- 基本屬性 url、user、password -->
        <property name="url" value="${db.url}" />
        <property name="username" value="${db.username}" />
        <property name="password" value="${db.password}" />

        <!-- 配置初始化大小、最小、最大 -->
        <property name="initialSize" value="1" />
        <property name="minIdle" value="1" />
        <property name="maxActive" value="20" />

        <!-- 配置獲取連接等待超時的時間 -->
        <property name="maxWait" value="60000" />

        <!-- 配置間隔多久才進行一次檢測,檢測需要關閉的空閒連接,單位是毫秒 -->
        <property name="timeBetweenEvictionRunsMillis" value="60000" />

        <!-- 配置一個連接在池中最小生存的時間,單位是毫秒 -->
        <property name="minEvictableIdleTimeMillis" value="300000" />

        <property name="validationQuery" value="SELECT 'x'" />
        <property name="testWhileIdle" value="true" />
        <property name="testOnBorrow" value="false" />
        <property name="testOnReturn" value="false" />

        <!-- 打開PSCache,並且指定每個連接上PSCache的大小 -->
        <property name="poolPreparedStatements" value="true" />
        <property name="maxPoolPreparedStatementPerConnectionSize" value="20" />

        <!-- 配置監控統計攔截的filters,去掉後監控界面sql無法統計 -->
        <property name="filters" value="stat" />
    </bean>
    <bean id="db2" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">

        <!-- 數據源驅動類可不寫,Druid默認會自動根據URL識別DriverClass -->
        <property name="driverClassName" value="${db.driver2}" />
        <!-- 基本屬性 url、user、password -->
        <property name="url" value="${db.url2}" />
        <property name="username" value="${db.username2}" />
        <property name="password" value="${db.password2}" />
......此處省略
    </bean>
    <bean id="db_oracle" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">

        <!-- 數據源驅動類可不寫,Druid默認會自動根據URL識別DriverClass -->
        <property name="driverClassName" value="${db.driver3}" />
        <!-- 基本屬性 url、user、password -->
        <property name="url" value="${db.url3}" />
        <property name="username" value="${db.username3}" />
        <property name="password" value="${db.password3}" />

......此處省略
    </bean>

這裏我配置了三個數據源 , 前兩個是 mysql,最後一個是oracle 注意oracle 在配置的時候<property name="validationQuery" value="SELECT 'x' FROM DUAL" />
然後就是 數據源管理配置

 <!-- 動態配置數據源 -->  
   <bean id ="dataSource" class= "xxx.xxx.xxx.DynamicDataSource" >  
          <property name ="targetDataSources">  
                <map key-type ="java.lang.String"> 
                <!-- key: 在代碼中切換數據源所使用的key. value-ref 爲xml中數據源的配置 id --> 
                      <entry value-ref ="db1" key= "db1"></entry >  
                      <entry value-ref ="db2" key="db2"></entry>  
                      <entry value-ref ="db_oracle" key="db_oracle"></entry>  

                </map >  
          </property >  
   </bean >  

然後就是數據源工廠的配置,這裏就不給出代碼了,
5) 我是在業務層切換數據源的

    /**
     * 第三個數據源的數據
     */
    public DbTest search(DbTest bean) throws Exception {

        // 第三個數據源的數據
        DataSourceContextHolder.setDbType(DataSourceType.SOURCE_ORACLE);
        bean =  dbTestDao.search(bean);

        return bean;
    }

然後把項目跑起來 ,測試代碼大家就自己寫吧,可以寫 jsp 頁面,也可以用 Junit 測試,下面是我的測試結果
這裏寫圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章