多數據源配置(MyBatis-Plus vs AbstractRoutingDataSource)

MyBatis-Plus vs AbstractRoutingDataSource

MyBatis-Plus多數據源配

1.添加依賴

<dependency><groupId>com.baomidou</groupId><artifactId>dynamic-datasource-spring-boot-starter</artifactId><version>3.5.0</version>
</dependency>

2.配置數據源信息

spring:datasource:dynamic:primary: master  # 設置默認數據源datasource:master:  # 主數據源url: jdbc:mysql://localhost:3306/master_dbusername: rootpassword: 123456driver-class-name: com.mysql.cj.jdbc.Driverslave:  # 從數據源url: jdbc:mysql://localhost:3306/slave_dbusername: rootpassword: 123456driver-class-name: com.mysql.cj.jdbc.Driver

3.使用 @DS 注解切換數據源
在Service類或方法上使用 @DS(“數據源名稱”) 指定數據源

@Service
@DS("master")  // 類級別默認數據源
public class UserServiceImpl implements UserService {@Autowiredprivate UserMapper userMapper;@Override@DS("slave")  // 方法級別覆蓋類級別數據源public User getUserById(Long id) {return userMapper.selectById(id);}
}

4.排除原生自動配置(可選)
如果出現沖突,在啟動類排除原生數據源自動配置:

@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
public class Application {public static void main(String[] args) {SpringApplication.run(Application.class, args);}
}

5.多數據源的事務一致性(@DSTransactional注解)

@DSTransactionalpublic void test() {//db1數據源DeAnOrganization deAnOrganization = new DeAnOrganization();deAnOrganization.setId(1L);deAnOrganizationMapper.insert(deAnOrganization);//db2數據源	JdfLightBasic jdfLightBasic = new JdfLightBasic();jdfLightBasic.setOrgId("1");jdfLightBasicMapper.insert(jdfLightBasic);//拋出異常,@DSTransactional可保證事務唯一性,事務可正常回滾throw new RuntimeException("test");}

AbstractRoutingDataSource

使用 AbstractRoutingDataSource 配置多數據源是 Spring 原生的動態數據源解決方案,適合需要深度定制的場景。
1.依賴僅需引入jdbc+連接池

<!-- 僅需 Spring JDBC + 連接池(使用druid) -->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version>1.2.8</version>
</dependency>

2.數據源配置

spring:datasource:master:url: jdbc:mysql://localhost:3306/master_dbusername: rootpassword: 123456driver-class-name: com.mysql.cj.jdbc.Drivertype: com.alibaba.druid.pool.DruidDataSourcedruid:initial-size: 5max-active: 20slave:url: jdbc:mysql://localhost:3306/slave_dbusername: rootpassword: 123456driver-class-name: com.mysql.cj.jdbc.Drivertype: com.alibaba.druid.pool.DruidDataSourcedruid:initial-size: 3max-active: 15

3.創建數據源上下文持有類

public class DataSourceContextHolder {private static final ThreadLocal<String> CONTEXT = new ThreadLocal<>();public static void setDataSource(String dsName) {CONTEXT.set(dsName);}public static String getDataSource() {return CONTEXT.get();}public static void clear() {CONTEXT.remove();}
}

4.實現動態數據源路由

public class DynamicDataSource extends AbstractRoutingDataSource {@Overrideprotected Object determineCurrentLookupKey() {return DataSourceContextHolder.getDataSource();}
}

5.配置數據源Bean

@Configuration
@MapperScan(basePackages = "com.example.mapper")
public class DataSourceConfig {@Bean@ConfigurationProperties(prefix = "spring.datasource.master")public DataSource masterDataSource() {return DruidDataSourceBuilder.create().build();}@Bean@ConfigurationProperties(prefix = "spring.datasource.slave")public DataSource slaveDataSource() {return DruidDataSourceBuilder.create().build();}@Bean@Primarypublic DataSource dynamicDataSource(@Qualifier("masterDataSource") DataSource master,@Qualifier("slaveDataSource") DataSource slave) {Map<Object, Object> targetDataSources = new HashMap<>();targetDataSources.put("master", master);targetDataSources.put("slave", slave);DynamicDataSource ds = new DynamicDataSource();ds.setDefaultTargetDataSource(master); // 默認數據源ds.setTargetDataSources(targetDataSources);ds.afterPropertiesSet();return ds;}// 配置事務管理器@Beanpublic PlatformTransactionManager transactionManager(DataSource dynamicDataSource) {return new DataSourceTransactionManager(dynamicDataSource);}
}

6.自定義注解實現切換

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DS {String value() default "master";
}// 切面實現
@Aspect
@Component
public class DSAspect {@Before("@annotation(ds)")public void beforeSwitchDS(JoinPoint point, DS ds) {DataSourceContextHolder.setDataSource(ds.value());}@After("@annotation(ds)")public void afterSwitchDS(JoinPoint point, DS ds) {DataSourceContextHolder.clear();}
}

7.使用示例

@Service
public class UserService {@Autowiredprivate UserMapper userMapper;@DS("master") // 使用主庫public void addUser(User user) {userMapper.insert(user);}@DS("slave") // 使用從庫public User getUser(Long id) {return userMapper.selectById(id);}
}

8.事務管理器配置

@Configuration
public class TransactionConfig {// 主庫事務管理器@Beanpublic PlatformTransactionManager masterTransactionManager(@Qualifier("masterDataSource") DataSource dataSource) {return new DataSourceTransactionManager(dataSource);}// 從庫事務管理器@Beanpublic PlatformTransactionManager slaveTransactionManager(@Qualifier("slaveDataSource") DataSource dataSource) {return new DataSourceTransactionManager(dataSource);}
}
// 自定義數據源切換注解
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DS {String value() default "master";
}// 數據源切換切面(需優先于事務切面執行)
@Aspect
@Component
@Order(0) // 優先級高于 @Transactional 的切面
public class DSAspect {@Before("@annotation(ds)")public void beforeSwitchDS(JoinPoint joinPoint, DS ds) {DataSourceContextHolder.setDataSource(ds.value());}@After("@annotation(ds)")public void afterSwitchDS(JoinPoint joinPoint, DS ds) {DataSourceContextHolder.clear();}
}
@Service
public class BusinessService {// 顯式指定事務管理器@DS("master")@Transactional(transactionManager = "masterTransactionManager")public void createOrder(Order order) {// 主庫操作}@DS("slave")@Transactional(transactionManager = "slaveTransactionManager")public Order queryOrder(Long id) {// 從庫查詢}// 跨數據源事務(需要分布式事務支持)@DS("master")@Transactional(transactionManager = "masterTransactionManager")public void crossDataSourceOperation() {// 主庫操作slaveOperation(); // 需要新事務}@DS("slave")@Transactional(transactionManager = "slaveTransactionManager", propagation = Propagation.REQUIRES_NEW)public void slaveOperation() {// 從庫操作(獨立事務)}
}

關鍵注意事項

AOP 執行順序
必須確保數據源切換切面(@DS)先于事務切面執行:
// 啟動類配置
@SpringBootApplication
@EnableTransactionManagement(order = Ordered.LOWEST_PRECEDENCE) // 事務切面最后執行
public class Application { ... }事務傳播機制
默認 Propagation.REQUIRED 會繼承當前事務的數據源
使用 Propagation.REQUIRES_NEW 可強制開啟新事務并切換數據源分布式事務支持
如需跨數據源事務原子性,需集成 Seata 等分布式事務框架:
@DS("master")
@GlobalTransactional // Seata 全局事務注解
public void distributedTransaction() {// 操作多個數據源
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/902286.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/902286.shtml
英文地址,請注明出處:http://en.pswp.cn/news/902286.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

聊透多線程編程-線程互斥與同步-13. C# Mutex類實現線程互斥

目錄 一、什么是臨界區&#xff1f; 二、Mutex類簡介 三、Mutex的基本用法 解釋&#xff1a; 四、Mutex的工作原理 五、使用示例1-保護共享資源 解釋&#xff1a; 六、使用示例2-跨進程同步 示例場景 1. 進程A - 主進程 2. 進程B - 第二個進程 輸出結果 ProcessA …

stm32week12

stm32學習 九.stm32與HAL庫 2.HAL庫框架 總架構&#xff1a; 文件介紹&#xff1a; ppp是某一外設&#xff0c;ex是拓展功能 HAL庫API函數和變量命名規則&#xff1a; HAL庫對寄存器位操作的相關宏定義&#xff1a; HAL庫的回調函數&#xff1a; 3.STM32啟動過程 MDK編譯過…

opencv HSV的具體描述

色調H&#xff1a; 使用角度度量&#xff0c;取值范圍為0\~360&#xff0c;從紅色開始按逆時針方向計算&#xff0c;紅色為0&#xff0c;綠色為120&#xff0c;藍色為240。它們的補色是&#xff1a;黃色為60&#xff0c;青色為180&#xff0c;紫色為300。通過改變H的值&#x…

Java Lambda表達式指南

一、Lambda表達式基礎 1. 什么是Lambda表達式&#xff1f; 匿名函數&#xff1a;沒有名稱的函數函數式編程&#xff1a;可作為參數傳遞的代碼塊簡潔語法&#xff1a;替代匿名內部類的更緊湊寫法 2. 基本語法 (parameters) -> expression 或 (parameters) -> { statem…

面向對象設計中的類的分類:實體類、控制類和邊界類

目錄 前言1. 實體類&#xff08;Entity Class&#xff09;1.1 定義和作用1.2 實體類的特點1.3 實體類的示例 2. 控制類&#xff08;Control Class&#xff09;2.1 定義和作用2.2 控制類的特點2.3 控制類的示例 3. 邊界類&#xff08;Boundary Class&#xff09;3.1 定義和作用3…

C# 封裝教程

原文&#xff1a;C# 封裝_w3cschool &#xff08;注&#xff1a;本文為教程文章&#xff0c;請勿標記為付費文章&#xff01;特此聲明&#xff09; 封裝 被定義為"把一個或多個項目封閉在一個物理的或者邏輯的包中"。在面向對象程序設計方法論中&#xff0c;封裝是…

量化交易 - RSRS(阻力支撐相對強度)- 正確用法 - 年均收益18%

經過研究&#xff0c;發現RSRS的正確用法其實是需要用到兩個數據&#xff0c;分別是 n: 一階擬合樣本數&#xff0c;m:求均值方差樣本數&#xff0c;其中n比較小 如18&#xff0c;m比較大 如1100 經過調優后&#xff0c;收益率顯著上升&#xff01; 如下圖&#xff1a; &…

Oracle expdp的 EXCLUDE 參數詳解

Oracle expdp的 EXCLUDE 參數詳解 EXCLUDE 是 Oracle Data Pump Export (expdp) 工具中的一個關鍵參數&#xff0c;用于指定在導出過程中要排除的對象或對象類型。 一、基本語法 expdp username/password DUMPFILEexport.dmp DIRECTORYdpump_dir EXCLUDEobject_type[:name_c…

如何使用3DMAX插件PFSpliner將3D對象轉化為藝術樣條線?

什么是粒子流源(Particle Flow)是3DMAX的一個功能極其強大的粒子系統。它采用事件驅動模型,使用一個名為“粒子視圖”的特殊對話框。在“粒子視圖”中,您可以將描述粒子屬性(如形狀、速度、方向和一段時間內的旋轉)的單個運算符組合成稱為事件的組。每個操作符都提供一組…

【python】 循環語句(while)

1、循環語句 語法&#xff1a; while 條件:......... #只有條件為真時&#xff0c;才會執行while中的內容。 1.1循環語句基本使用 示例1&#xff1a; print("開始") while 1>2:print("人生得意須盡歡") print("結束") #輸出結果&#…

OOA-CNN-LSTM-Attention、CNN-LSTM-Attention、OOA-CNN-LSTM、CNN-LSTM四模型多變量時序預測一鍵對比

OOA-CNN-LSTM-Attention、CNN-LSTM-Attention、OOA-CNN-LSTM、CNN-LSTM四模型多變量時序預測一鍵對比 目錄 OOA-CNN-LSTM-Attention、CNN-LSTM-Attention、OOA-CNN-LSTM、CNN-LSTM四模型多變量時序預測一鍵對比預測效果基本介紹程序設計參考資料 預測效果 基本介紹 基于OOA-CN…

20250421在榮品的PRO-RK3566開發板的Android13下頻繁重啟RKNPU fde40000.npu: Adding to iommu gr

20250421在榮品的PRO-RK3566開發板的Android13下頻繁重啟RKNPU fde40000.npu: Adding to iommu gr 2025/4/21 14:50 緣起&#xff1a;電池沒電了&#xff0c;導致榮品的PRO-RK3566的核心板頻繁重啟。 內核時間4s就重啟。100%復現。 PRO-RK3566 Android13啟動到這里 復位&#…

動態監控進程

1.介紹: top和ps命令很相似,它們都是用來顯示正在執行的進程,top和ps最大的不同之處,在于top在執行中可以更新正在執行的進程. 2.基本語法&#xff1a; top [選項] 選項說明 ??僵死進程&#xff1a;內存沒有釋放,但是進程已經停止工作了,需要及時清理 交互操作說明 應用案…

657SJBH西藏藏藥特產銷售管理系統

畢業論文&#xff08;設計&#xff09;文獻綜述 西藏藏藥特產銷售管理系統的設計與實現 近年來&#xff0c;隨著網絡技術特別是Internet技術的普及和發展&#xff0c;電子商務的開發和應用成為一個熱門領域&#xff0c;在線藏藥特產銷售系統就是這其中的一員。 藏藥產業在西藏…

棧和隊列--數據結構初階(2)(C/C++)

文章目錄 前言理論部分棧的模擬實現STL中的棧容器隊列的模擬實現STL中的隊列容器 作業部分 前言 這期的話會給大家講解棧和隊列的模擬實現和在STL中棧和隊列怎么用的一些知識和習題部分(這部分側重于理論知識&#xff0c;習題倒還是不難) 理論部分 棧的模擬實現 typedef int…

RNN的理解

對于RNN的理解 import torch import torch.nn as nn import torch.nn.functional as F# 手動實現一個簡單的RNN class RNN(nn.Module):def __init__(self, input_size, hidden_size, output_size):super(RNN, self).__init__()# 定義權重矩陣和偏置項self.hidden_size hidden…

二叉查找樹和B樹

二叉查找樹&#xff08;Binary Search Tree, BST&#xff09;和 B 樹&#xff08;B-tree&#xff09;都是用于組織和管理數據的數據結構&#xff0c;但它們在結構、應用場景和性能方面有顯著區別。 二叉查找樹&#xff08;Binary Search Tree, BST&#xff09; 特點&#xff1…

一段式端到端自動駕駛:VAD:Vectorized Scene Representation for Efficient Autonomous Driving

論文地址&#xff1a;https://github.com/hustvl/VAD 代碼地址&#xff1a;https://arxiv.org/pdf/2303.12077 1. 摘要 自動駕駛需要對周圍環境進行全面理解&#xff0c;以實現可靠的軌跡規劃。以往的方法依賴于密集的柵格化場景表示&#xff08;如&#xff1a;占據圖、語義…

OpenCV訓練題

一、創建一個 PyQt 應用程序&#xff0c;該應用程序能夠&#xff1a; 使用 OpenCV 加載一張圖像。在 PyQt 的窗口中顯示這張圖像。提供四個按鈕&#xff08;QPushButton&#xff09;&#xff1a; 一個用于將圖像轉換為灰度圖一個用于將圖像恢復為原始彩色圖一個用于將圖像進行…

opencv函數展示4

一、形態學操作函數 1.基本形態學操作 &#xff08;1&#xff09;cv2.getStructuringElement() &#xff08;2&#xff09;cv2.erode() &#xff08;3&#xff09;cv2.dilate() 2.高級形態學操作 &#xff08;1&#xff09;cv2.morphologyEx() 二、直方圖處理函數 1.直方圖…