首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

Spring + MyBatis 多數據源配置實戰:基於 AbstractRoutingDataSource 動態切換

     編輯:Java 綜合教學

Spring + MyBatis 多數據源配置實戰:基於 AbstractRoutingDataSource 動態切換

採用 Spring 的 AbstractRoutingDataSource 實現運行期根據業務邏輯動態切換數據源,核心在於 ThreadLocal 綁定當前線程的數據源標識。

1. 核心配置文件

spring-datasource.xml 定義兩個 Druid 數據源與路由數據源

<beans ...>
  <!-- 主數據源 -->
  <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
    <property name="driverClassName" value="${jdbc.driverClassName}"/>
    <property name="url" value="${jdbc.url}"/>
    <property name="username" value="${jdbc.username}"/>
    <property name="password" value="${jdbc.password}"/>
    <property name="maxActive" value="${jdbc.pool.maxActive}"/>
    <property name="maxIdle" value="${jdbc.pool.maxIdle}"/>
    <property name="minIdle" value="${jdbc.pool.minIdle}"/>
  </bean>

  <!-- 次數據源 -->
  <bean id="dataSource_1" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
    <property name="driverClassName" value="${jdbc.driverClassName}"/>
    <property name="url" value="${jdbc.url1}"/>
    <property name="username" value="${jdbc.username}"/>
    <property name="password" value="${jdbc.password}"/>
    <property name="maxActive" value="${jdbc.pool.maxActive}"/>
    <property name="maxIdle" value="${jdbc.pool.maxIdle}"/>
    <property name="minIdle" value="${jdbc.pool.minIdle}"/>
  </bean>

  <!-- 路由數據源:默認走 dataSource,通過 key 切換 -->
  <bean id="multipleDataSource" class="cn.tomcat.quickstart.common.utils.MultipleDataSource">
    <property name="defaultTargetDataSource" ref="dataSource"/>
    <property name="targetDataSources">
      <map><entry key="dataSource_1" value-ref="dataSource_1"/></map>
    </property>
  </bean>

  <!-- 事務管理器綁定路由數據源 -->
  <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="multipleDataSource"/>
  </bean>
</beans>

jdbc.properties

jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/quickstart?useUnicode=true&characterEncoding=utf-8
jdbc.url1=jdbc:mysql://localhost:3306/quickstart1?useUnicode=true&characterEncoding=utf-8
jdbc.username=root
jdbc.password=password
jdbc.pool.maxActive=50
jdbc.pool.maxIdle=10
jdbc.pool.minIdle=0

2. 路由實現類 MultipleDataSource.java

package cn.tomcat.quickstart.common.utils;

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

public class MultipleDataSource extends AbstractRoutingDataSource {
    private static final ThreadLocal<String> dataSourceKey = new InheritableThreadLocal<>();

    public static void setDataSourceKey(String dataSource) {
        dataSourceKey.set(dataSource);
    }

    @Override
    protected Object determineCurrentLookupKey() {
        return dataSourceKey.get(); // 返回當前線程綁定的 key
    }
}

3. 業務代碼中切換數據源

// 默認使用 dataSource
// 需要切換到次庫時:
MultipleDataSource.setDataSourceKey("dataSource_1");
try {
    // 執行次庫操作
} finally {
    // 清理或切回默認
    MultipleDataSource.setDataSourceKey("dataSource");
}

關鍵點總結

  • 使用 InheritableThreadLocal 支援父子線程傳遞。
  • 事務管理器必須綁定 multipleDataSource,否則事務邊界內可能切換數據源導致不一致。
  • 切換後務必在 finally 中恢復,防止線程池復用時污染後續請求。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved