最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

MyBatis動(dòng)態(tài)數(shù)據(jù)源切換的完整方案

 更新時(shí)間:2025年08月26日 09:27:26   作者:墨瑾軒  
在微服務(wù)架構(gòu)和分布式系統(tǒng)中,動(dòng)態(tài)數(shù)據(jù)源是應(yīng)對(duì)多環(huán)境切換、讀寫分離、多租戶等復(fù)雜場(chǎng)景的核心工具,MyBatis 與 Spring 結(jié)合后,可以靈活實(shí)現(xiàn)數(shù)據(jù)源的動(dòng)態(tài)切換,以下是實(shí)現(xiàn) MyBatis 動(dòng)態(tài)數(shù)據(jù)源的完整方案,需要的朋友可以參考下

在微服務(wù)架構(gòu)和分布式系統(tǒng)中,動(dòng)態(tài)數(shù)據(jù)源是應(yīng)對(duì)多環(huán)境切換、讀寫分離、多租戶等復(fù)雜場(chǎng)景的核心工具。MyBatis 與 Spring 結(jié)合后,通過 AbstractRoutingDataSource線程上下文管理ThreadLocal),可以靈活實(shí)現(xiàn)數(shù)據(jù)源的動(dòng)態(tài)切換。以下是實(shí)現(xiàn) MyBatis 動(dòng)態(tài)數(shù)據(jù)源的完整方案,涵蓋核心步驟、代碼示例和最佳實(shí)踐。

1. 核心概念

  • 動(dòng)態(tài)數(shù)據(jù)源:根據(jù)業(yè)務(wù)需求自動(dòng)選擇不同的數(shù)據(jù)庫連接(如主庫、從庫、測(cè)試庫)。
  • AbstractRoutingDataSource:Spring 提供的抽象類,負(fù)責(zé)動(dòng)態(tài)決定當(dāng)前使用哪個(gè)數(shù)據(jù)源。
  • ThreadLocal:線程安全的上下文管理工具,保存當(dāng)前線程的數(shù)據(jù)源標(biāo)識(shí)(如 master、slave)。

2. 實(shí)現(xiàn)步驟

(1) 配置多個(gè)數(shù)據(jù)源

application.ymlapplication.properties 中定義多個(gè)數(shù)據(jù)源配置:

spring:
  datasource:
    master:
      url: jdbc:mysql://localhost:3306/master_db
      username: root
      password: root
      driver-class-name: com.mysql.cj.jdbc.Driver
    slave:
      url: jdbc:mysql://localhost:3306/slave_db
      username: root
      password: root
      driver-class-name: com.mysql.cj.jdbc.Driver

(2) 創(chuàng)建動(dòng)態(tài)數(shù)據(jù)源類

繼承 AbstractRoutingDataSource,重寫 determineCurrentLookupKey 方法:

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

public class DynamicDataSource extends AbstractRoutingDataSource {
    @Override
    protected Object determineCurrentLookupKey() {
        // 從線程上下文中獲取當(dāng)前數(shù)據(jù)源標(biāo)識(shí)
        return DataSourceContextHolder.getDataSource();
    }
}

(3) 數(shù)據(jù)源上下文管理

使用 ThreadLocal 保存當(dāng)前線程的數(shù)據(jù)源標(biāo)識(shí):

public class DataSourceContextHolder {
    private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();

    public static void setDataSource(String dataSource) {
        contextHolder.set(dataSource);
    }

    public static String getDataSource() {
        return contextHolder.get();
    }

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

(4) 配置動(dòng)態(tài)數(shù)據(jù)源 Bean

在 Spring 配置類中定義動(dòng)態(tài)數(shù)據(jù)源,并綁定多個(gè)數(shù)據(jù)源:

@Configuration
public class DataSourceConfig {

    @Bean(name = "masterDataSource")
    @ConfigurationProperties(prefix = "spring.datasource.master")
    public DataSource masterDataSource() {
        return DataSourceBuilder.create().build();
    }

    @Bean(name = "slaveDataSource")
    @ConfigurationProperties(prefix = "spring.datasource.slave")
    public DataSource slaveDataSource() {
        return DataSourceBuilder.create().build();
    }

    @Bean
    @Primary
    public DataSource dynamicDataSource(
        @Qualifier("masterDataSource") DataSource masterDataSource,
        @Qualifier("slaveDataSource") DataSource slaveDataSource) {
        
        Map<Object, Object> targetDataSources = new HashMap<>();
        targetDataSources.put("master", masterDataSource);
        targetDataSources.put("slave", slaveDataSource);

        DynamicDataSource dynamicDataSource = new DynamicDataSource();
        dynamicDataSource.setTargetDataSources(targetDataSources);
        dynamicDataSource.setDefaultTargetDataSource(masterDataSource); // 默認(rèn)使用主數(shù)據(jù)源
        return dynamicDataSource;
    }
}

(5) 整合 MyBatis

配置 SqlSessionFactoryMapperScannerConfigurer,確保使用動(dòng)態(tài)數(shù)據(jù)源:

@Configuration
@MapperScan(basePackages = "com.example.mapper")
public class MyBatisConfig {

    @Autowired
    private DataSource dynamicDataSource;

    @Bean
    public SqlSessionFactory sqlSessionFactory() throws Exception {
        SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
        factoryBean.setDataSource(dynamicDataSource);
        return factoryBean.getObject();
    }
}

(6) 動(dòng)態(tài)切換數(shù)據(jù)源

在業(yè)務(wù)代碼中通過 DataSourceContextHolder 設(shè)置數(shù)據(jù)源標(biāo)識(shí):

// 切換到從數(shù)據(jù)源(讀操作)
DataSourceContextHolder.setDataSource("slave");
try {
    // 執(zhí)行查詢操作
    List<User> users = userMapper.selectAll();
} finally {
    // 清除線程上下文
    DataSourceContextHolder.clearDataSource();
}

// 切換到主數(shù)據(jù)源(寫操作)
DataSourceContextHolder.setDataSource("master");
try {
    userMapper.insert(user);
} finally {
    DataSourceContextHolder.clearDataSource();
}

(7) 事務(wù)管理

為每個(gè)數(shù)據(jù)源配置獨(dú)立的事務(wù)管理器,并通過 @Transactional 注解指定事務(wù)管理器:

@Configuration
@EnableTransactionManagement
public class TransactionConfig {

    @Bean(name = "masterTransactionManager")
    public PlatformTransactionManager masterTransactionManager(
        @Qualifier("masterDataSource") DataSource masterDataSource) {
        return new DataSourceTransactionManager(masterDataSource);
    }

    @Bean(name = "slaveTransactionManager")
    public PlatformTransactionManager slaveTransactionManager(
        @Qualifier("slaveDataSource") DataSource slaveDataSource) {
        return new DataSourceTransactionManager(slaveDataSource);
    }
}

// 在 Service 層指定事務(wù)管理器
@Service
public class UserService {

    @Transactional("masterTransactionManager")
    public void insertUser(User user) {
        userMapper.insert(user);
    }

    @Transactional("slaveTransactionManager")
    public List<User> selectAllUsers() {
        return userMapper.selectAll();
    }
}

3. 使用場(chǎng)景

讀寫分離

  • 寫操作(INSERT/UPDATE/DELETE)使用主庫,讀操作(SELECT)使用從庫。
  • 示例:訂單寫入主庫,訂單查詢從庫。

多環(huán)境切換

  • 開發(fā)環(huán)境、測(cè)試環(huán)境、生產(chǎn)環(huán)境分別綁定不同的數(shù)據(jù)源。
  • 示例:通過配置文件切換不同數(shù)據(jù)庫地址。

多租戶隔離

  • 每個(gè)租戶使用獨(dú)立的數(shù)據(jù)源,通過租戶標(biāo)識(shí)動(dòng)態(tài)切換。
  • 示例:企業(yè)級(jí) SaaS 系統(tǒng),不同企業(yè)訪問不同數(shù)據(jù)庫。

4. 注意事項(xiàng)

線程安全

  • 確保 ThreadLocal 在異步任務(wù)中傳遞數(shù)據(jù)源標(biāo)識(shí)(如使用 InheritableThreadLocalTransmittableThreadLocal)。

事務(wù)一致性

  • 跨數(shù)據(jù)源的事務(wù)需謹(jǐn)慎處理,避免臟讀或數(shù)據(jù)不一致??墒褂梅植际绞聞?wù)框架(如 Seata)。

性能優(yōu)化

  • 避免頻繁切換數(shù)據(jù)源,合理設(shè)計(jì)讀寫分離策略。

異常處理

  • 捕獲數(shù)據(jù)源切換異常,提供回退機(jī)制(如默認(rèn)使用主數(shù)據(jù)源)。

5. 總結(jié)

特性實(shí)現(xiàn)方式
動(dòng)態(tài)切換AbstractRoutingDataSource + ThreadLocal
讀寫分離通過業(yè)務(wù)邏輯判斷操作類型,設(shè)置 master/slave
多環(huán)境支持通過配置文件區(qū)分不同環(huán)境的數(shù)據(jù)源
事務(wù)管理為每個(gè)數(shù)據(jù)源配置獨(dú)立的 PlatformTransactionManager
線程安全使用 ThreadLocal 保存上下文,異步場(chǎng)景需傳遞上下文

通過以上方案,MyBatis 動(dòng)態(tài)數(shù)據(jù)源可以靈活適配多種業(yè)務(wù)場(chǎng)景,成為多環(huán)境切換的“神器”。結(jié)合 Spring 的強(qiáng)大生態(tài),開發(fā)者可以輕松實(shí)現(xiàn)高可用、高性能的分布式系統(tǒng)。

以上就是MyBatis動(dòng)態(tài)數(shù)據(jù)源切換的完整方案的詳細(xì)內(nèi)容,更多關(guān)于MyBatis動(dòng)態(tài)數(shù)據(jù)源切換的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 全面詳解java代碼重構(gòu)與設(shè)計(jì)模式

    全面詳解java代碼重構(gòu)與設(shè)計(jì)模式

    這篇文章主要為大家介紹了全面詳解java代碼重構(gòu)與設(shè)計(jì)模式的全面詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-06-06
  • SpringBoot實(shí)現(xiàn)多租戶系統(tǒng)架構(gòu)的5種設(shè)計(jì)方案介紹

    SpringBoot實(shí)現(xiàn)多租戶系統(tǒng)架構(gòu)的5種設(shè)計(jì)方案介紹

    多租戶(Multi-tenancy)是一種軟件架構(gòu)模式,允許單個(gè)應(yīng)用實(shí)例服務(wù)于多個(gè)客戶(租戶),同時(shí)保持租戶數(shù)據(jù)的隔離性和安全性,本文分享了SpringBoot環(huán)境下實(shí)現(xiàn)多租戶系統(tǒng)的5種架構(gòu)設(shè)計(jì)方案,需要的可以參考一下
    2025-05-05
  • 關(guān)于String轉(zhuǎn)Json的幾種方式

    關(guān)于String轉(zhuǎn)Json的幾種方式

    這篇文章主要介紹了關(guān)于String轉(zhuǎn)Json的幾種方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-12-12
  • Java設(shè)計(jì)模式筆記之Builder模式

    Java設(shè)計(jì)模式筆記之Builder模式

    建造者模式是日常開發(fā)中比較常見的設(shè)計(jì)模式,它的主要作用就是將復(fù)雜事物創(chuàng)建的過程抽象出來,該抽象的不同實(shí)現(xiàn)方式不同,創(chuàng)建出的對(duì)象也不同,這篇文章主要給大家介紹了關(guān)于Java設(shè)計(jì)模式筆記之Builder模式的相關(guān)資料,需要的朋友可以參考下
    2022-03-03
  • 基于JavaMail實(shí)現(xiàn)郵件發(fā)送

    基于JavaMail實(shí)現(xiàn)郵件發(fā)送

    這篇文章主要為大家詳細(xì)介紹了基于JavaMail實(shí)現(xiàn)郵件發(fā)送功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-03-03
  • java 使用簡單的demo實(shí)例告訴你優(yōu)化算法的強(qiáng)大

    java 使用簡單的demo實(shí)例告訴你優(yōu)化算法的強(qiáng)大

    本篇文章介紹了,在java中使用簡單的demo實(shí)例告訴你優(yōu)化算法的強(qiáng)大。需要的朋友參考下
    2013-05-05
  • mybatisplus之Wrappers.ne踩坑記錄解決

    mybatisplus之Wrappers.ne踩坑記錄解決

    這篇文章主要為大家介紹了mybatisplus之Wrappers.ne踩坑記錄解決,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-05-05
  • Java連接Redis的兩種方式

    Java連接Redis的兩種方式

    Redis 是一種高性能的鍵值存儲(chǔ)數(shù)據(jù)庫,廣泛應(yīng)用于緩存、消息隊(duì)列、會(huì)話存儲(chǔ)等場(chǎng)景,Java 作為一門廣泛使用的編程語言,提供了多種方式來連接和操作 Redis,本文將介紹兩種常用的 Java 連接 Redis 的方式,需要的朋友可以參考下
    2025-03-03
  • Mybatis-plus對(duì)單表操作的封裝實(shí)現(xiàn)

    Mybatis-plus對(duì)單表操作的封裝實(shí)現(xiàn)

    本文詳細(xì)介紹了MyBatis-Plus單表操作,包括自定義SQL、邏輯刪除、樂觀鎖、全局?jǐn)r截器和代碼生成器等,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-12-12
  • java與C 代碼運(yùn)行效率的對(duì)比(整理)

    java與C 代碼運(yùn)行效率的對(duì)比(整理)

    最近和朋友無意間討論起了 有關(guān)java 和C 的 效率問題, (我是java 推介者, 他是 c 語言推介者, 他做的是嵌入式)故,想通過網(wǎng)絡(luò)查詢一下, 總結(jié)一下,兩者到底效率如何,其有何差異,原因又是啥?各種優(yōu)勢(shì)有在何處?
    2021-04-04

最新評(píng)論

光山县| 读书| 宁都县| 望江县| 稻城县| 伊通| 阿城市| 平罗县| 新疆| 三穗县| 礼泉县| 平阴县| 高尔夫| 民县| 南宫市| 上栗县| 咸宁市| 寻甸| 顺昌县| 灵台县| 庐江县| 琼结县| 五台县| 大悟县| 花垣县| 台山市| 琼海市| 大关县| 巴马| 淮北市| 和平区| 静海县| 凭祥市| 广昌县| 阳曲县| 炉霍县| 邢台县| 武功县| 都兰县| 巴青县| 长乐市|