springboot配置多數據源以及事務問題

一、背景以及為什么需要學習

在高并發的項目中,單數據庫已無法承載大數據量的訪問,因此需要使用多個數據庫進行對數據的讀寫分離,此外就是在微服化的今天,我們在項目中可能采用各種不同存儲,因此也需要連接不同的數據庫,居于這樣的背景,這里簡單分享實現的思路以及實現方案

二、實現方式

多數據源實現思路有兩種,一種是通過配置多個SqlSessionFactory實現多數據源;

1、通過配置多個SqlSessionFactory實現多數據源在這里插入圖片描述

2、通過Spring提供的AbstractRoutingDataSource抽象了一個DynamicDataSource實現動態切換數據源

在這里插入圖片描述

三、方式一:不同庫的Mapper指定不同的SqlSessionFactory

1 針對不同的庫分別放置對用不同的SqlSessionFactory

UserDataSourceConfiguration

@Configuration
@MapperScan(basePackages = "org.datasource.demo1.usermapper",sqlSessionFactoryRef = "userSqlSessionFactory")
public class UserDataSourceConfiguration {public static final String MAPPER_LOCATION = "classpath:usermapper/*.xml";@Primary@Bean("userDataSource")@ConfigurationProperties(prefix = "spring.datasource.user")public DataSource userDataSource() {return DataSourceBuilder.create().build();}@Bean(name = "userTransactionManager")@Primarypublic PlatformTransactionManager userTransactionManager(@Qualifier("userDataSource") DataSource dataSource) {return new DataSourceTransactionManager(dataSource);}@Primary@Bean(name = "userSqlSessionFactory")public SqlSessionFactory userSqlSessionFactory(@Qualifier("userDataSource") DataSource dataSource) throws Exception {final SqlSessionFactoryBean sessionFactoryBean = new SqlSessionFactoryBean();sessionFactoryBean.setDataSource(dataSource);sessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(UserDataSourceConfiguration.MAPPER_LOCATION));return sessionFactoryBean.getObject();}}

SoulDataSourceConfiguration

@Configuration
@MapperScan(basePackages = "org.datasource.demo1.soulmapper",sqlSessionFactoryRef = "soulSqlSessionFactory")
public class SoulDataSourceConfiguration {public static final String MAPPER_LOCATION = "classpath:soulmapper/*.xml";@Bean("soulDataSource")@ConfigurationProperties(prefix = "spring.datasource.soul")public DataSource soulDataSource() {return DataSourceBuilder.create().build();}@Bean(name = "soulTransactionManager")public PlatformTransactionManager soulTransactionManager(@Qualifier("soulDataSource") DataSource dataSource) {return new DataSourceTransactionManager(dataSource);}@Bean(name = "soulSqlSessionFactory")public SqlSessionFactory soulSqlSessionFactory(@Qualifier("soulDataSource") DataSource dataSource) throws Exception {final SqlSessionFactoryBean sessionFactoryBean = new SqlSessionFactoryBean();sessionFactoryBean.setDataSource(dataSource);sessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(SoulDataSourceConfiguration.MAPPER_LOCATION));return sessionFactoryBean.getObject();}}

2 使用和測試

@Service
public class AppAuthService {@Autowiredprivate AppAuthMapper appAuthMapper;@Transactional(rollbackFor = Exception.class)public int getCount() {int a = appAuthMapper.listCount();int b = 1 / 0;return a;}}@SpringBootTest
@RunWith(SpringRunner.class)
public class TestDataSource {@Autowiredprivate AppAuthService appAuthService;@Autowiredprivate SysUserService sysUserService;@Testpublic void test_dataSource1(){int b=sysUserService.getCount();int a=appAuthService.getCount();}
}

3 總結

此種方式使用起來分層明確,不存在任何冗余代碼,不足地方就是每個庫都需要對應一個配置類,該配置類中實現方式都基本類似,該種解決方案每個配置類中都存在事務管理器,因此不需要單獨再去額外的關注。在使用時需要指定事務管理器

四、AOP+自定義注解

關于采用Spring AOP方式實現原理就是把多個數據源存儲在一個 Map中,當需要使用某個數據源時,從 Map中獲取此數據源進行處理。
在這里插入圖片描述

1 AbstractRoutingDataSource

在Spring中提供了AbstractRoutingDataSource來實現此功能,繼承AbstractRoutingDataSource類并覆寫其determineCurrentLookupKey()方法就可以完成數據源切換,該方法只需要返回數據源key即可,也就是存放數據源的Map的key,接下來我們來看一下AbstractRoutingDataSource整體的繼承結構,看他是如何做到的。
在這里插入圖片描述
在整體的繼承結構上我們會發現AbstractRoutingDataSource最終是繼承于DataSource,因此當我們繼承AbstractRoutingDataSource是我們自身也是一個數據源,對于數據源必然有連接數據庫的動作,如下代碼:

public Connection getConnection() throws SQLException {return this.determineTargetDataSource().getConnection();
}public Connection getConnection(String username, String password) throws SQLException {return this.determineTargetDataSource().getConnection(username, password);
}

只是AbstractRoutingDataSource的getConnection()方法里實際是調用determineTargetDataSource()返回的數據源的getConnection()方法。

protected DataSource determineTargetDataSource() {Assert.notNull(this.resolvedDataSources, "DataSource router not initialized");Object lookupKey = this.determineCurrentLookupKey();DataSource dataSource = (DataSource)this.resolvedDataSources.get(lookupKey);if (dataSource == null && (this.lenientFallback || lookupKey == null)) {dataSource = this.resolvedDefaultDataSource;}if (dataSource == null) {throw new IllegalStateException("Cannot determine target DataSource for lookup key [" + lookupKey + "]");} else {return dataSource;}
}

該方法通過determineCurrentLookupKey()方法獲取一個key,通過key從resolvedDataSources中獲取數據源DataSource對象。determineCurrentLookupKey()是個抽象方法,需要繼承AbstractRoutingDataSource的類實現;而resolvedDataSources是一個Map<Object, DataSource>,里面應該保存當前所有可切換的數據源。

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

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

相關文章

點亮城市名片丨計訊物聯智慧燈桿系統在通訊基地的成功應用

項目背景 在國家新型城鎮化大背景下&#xff0c;十四五規劃綱要強調“加快數字化發展&#xff0c;建設數字中國”&#xff0c;明確提出“以數字化助推城鄉發展和治理模式創新”&#xff0c;全面提高城市的運行效率和宜居程度。 項目概況 為滿足燈桿燈光亮度的遠程智能管理、對…

記錄 android studio 通過安裝NDK 編譯C文件,得到需要的so文件

只怪自己太健忘&#xff0c;每次網上查了一圈&#xff0c;搞定后&#xff0c;再遇到又發現不會操作了&#xff0c;特此記下 不廢話直接上步驟 &#xff08;1&#xff09; 進入AS的settinging如下界面 &#xff08;2&#xff09;選中圖片箭頭兩個文件 進行下載 &#xff08;…

【知識管理】假設檢驗pvalue的計算

讓我們通過一個具體的例子來解釋P值的計算過程&#xff0c;假設我們有一個模型用于區分SCD&#xff08;亞臨床癡呆&#xff09;和HC&#xff08;健康對照&#xff09;的分裂。我們通過置換測試來計算模型性能的P值。 原始模型性能評估 首先&#xff0c;我們在原始數據集上運行…

web學習筆記(二十一)

目錄 1.構造函數創建對象 1.1規則 1.2 new關鍵字調用構造函數時&#xff0c;函數內部做了什么事情&#xff1f; 1.3總結 2.混合模式創建對象 3.JavaScript 繼承---借助構造函數 4.原型鏈 4.1原型鏈實現方法繼承 5.完美的組合繼承 6.call方法的使用 1.構造函數創建對象…

React之數據綁定以及表單處理

一、表單元素 像<input>、<textarea>、<option>這樣的表單元素不同于其他元素&#xff0c;因為他們可以通過用戶交互發生變化。這些元素提供的界面使響應用戶交互的表單數據處理更加容易 交互屬性&#xff0c;用戶對一下元素交互時通過onChange回調函數來監聽…

回溯例題(leetcode17/37)

文章目錄 leetcode37leetcode17 回溯跟枚舉差不多。要注意“回溯”&#xff0c;別忘記“回”之前把之前的改動都復原。 leetcode37 leetcode37是解數獨問題。本題保證有且僅有唯一解。 思路&#xff1a;先把空格子的位置存下來&#xff0c;然后對每一個空位置挨個枚舉1-9。枚…

Excel常用公式總結非常實用

16個最實用的Excel萬能公式 1、多條件判斷 IF(And(條件1,條件2..條件N),條件成立返回值) IF(or(條件1,條件2..條件N),條件成立返回值) 2、多條件查找 Lookup(1,0/((條件1*條件2*...條件N)),返回值區域&#xff09; 3、多條件求和 Sumifs(值區域,判斷區域1,條件1,判斷區域2,條…

Java 數據庫面試題解析(下)

20. Hash索引和B樹索引的區別&#xff1f;【重點】 hash索引&#xff1a;等值查詢效率高&#xff0c;不能排序&#xff0c;不能進行范圍查詢&#xff1b; B樹索引&#xff1a;數據有序&#xff0c;適合范圍查詢。 21. MySQL中三種鎖的級別&#xff1f;【了解】 表級鎖&…

2024最新精華版Java面試題之spring篇

目錄 一、Java面試題之spring篇 1、什么是spring? 2、你們項目中為什么使用Spring框架&#xff1f; 3、 Autowired和Resource關鍵字的區別&#xff1f; 4、依賴注入的方式有幾種&#xff0c;各是什么? 5、講一下什么是Spring容器&#xff1f; 6、說說你對Spring MVC的理…

Java畢業設計-基于springboot開發的私人健身與教練預約系統-畢業論文+答辯PPT(有源代碼)

文章目錄 前言一、畢設成果演示&#xff08;源代碼在文末&#xff09;二、畢設摘要展示1.開發說明2.需求分析3、系統功能結構 三、系統實現展示1、系統功能模塊2、后臺功能模塊2.1管理員功能2.2用戶功能2.3教練功能 四、畢設內容和源代碼獲取總結 [Java畢業設計-基于springboot…

Android 11.0 內置google tts語音包功能實現

1.前言 在11.0的系統rom產品開發中,在gms的相關項目對于文字轉語音包功能不是內置功能,需要自己下載google的tts語音包,然后內置,在設置 google tts語音包apk作為默認的tts語音引擎功能,接下來分析實現這個功能 2.內置google tts語音包功能實現的核心類 frameworks/ba…

Chat GPT4.0:開啟智能對話的新紀元

介紹 Chat GPT4.0是基于GPT4.0架構開發的一款強大的智能對話模型。作為人工智能領域的最新進展&#xff0c;Chat GPT4.0引領著智能對話技術的新紀元。本文將探討Chat GPT4.0的創新之處以及對智能對話發展的推動作用。 Chat GPT4.0的創新之處 Chat GPT4.0在前一版本的基礎上進…

c++知識點之 --引用

本質&#xff1a;給變量起別名 語法&#xff1a;數據類型 &別名 原名 特點&#xff1a;傳引用比傳值的效率高很多 注意事項&#xff1a; 引用必須初始化&#xff0c;且初始化不能為空。引用不能改變引用關系&#xff08;引用的底層是指針常量&#xff08;type * const …

前端 JS 經典:for-in 和 for-of 用法區別

1. for-in 對于 string, object, array 類型使用 for-in const str "qwe"; const arr ["yqcoder", "db"]; const obj {name: "yqcoder",age: 18, };for (let i in str) {console.log(i); // 0 1 2 } for (let i in arr) {console…

簡單數據類型和復雜數據類型

1. 簡單數據類型 null是個特例: 2. 復雜數據類型 3. 堆和棧 注意&#xff1a; JavaScript 中是沒有堆和棧的概念的&#xff0c;通過堆棧的概念可以更好的理解代碼的一些執行方式&#xff0c;便于將來學習其他語言。 4. 簡單數據類型傳參 總結&#xff1a;簡單數據類型傳參傳…

webview_h5與原生增加權限索取行為交互(Flutter)

應各大應用市場上架要求,增加權限索取行為用戶交互彈窗 詳細: https://developer.huawei.com/consumer/cn/doc/app/FAQ-faq-05#h1-1698326401789-0 flutter端使用permission_handler申請權限注冊一個MethodChannel,增加一個函數,提供安卓webview相機/麥克風等權限被觸發時回調…

C++寫入和讀取結構體到二進制文件

二進制文件速度快&#xff0c;空間效率高 寫入數據到二進制文件 #include<iostream> #include<fstream> using namespace std; int main() {// 定義一個結構體struct student{int id; // 學號char name[20]; // 姓名double score; // 成…

LeetCode 2369.檢查數組是否存在有效劃分:動態規劃(DP)

【LetMeFly】2369.檢查數組是否存在有效劃分&#xff1a;動態規劃(DP) 力扣題目鏈接&#xff1a;https://leetcode.cn/problems/check-if-there-is-a-valid-partition-for-the-array/ 給你一個下標從 0 開始的整數數組 nums &#xff0c;你必須將數組劃分為一個或多個 連續 子…

在線ai寫作,讓你隨時隨地創作優質內容

如今的ai技術已經滲透到我們生活的方方面面。其中&#xff0c;AI寫作成為了一個備受關注的領域。如今&#xff0c;我們可以利用在線ai寫作在任何時間、任何地點創作出優質的內容。 傳統的寫作過程需要大量的時間和精力。從構思到寫作再到修改&#xff0c;每一個環節都需要我們投…

Linux進程管理——top字段

目錄 1.top下半部分——進程狀態 2.top常用內部命令 3.top指定 ①top ②top -d 1 ③top -d 1 -p 10126 ④top -d 1 -p 10126,1 4.使用信號控制進程 1.top下半部分——進程狀態 PID&#xff1a;進程號 User&#xff1a;用戶 PR/NI&#xff1a;優先級 VIRT&#xff08…