SpringBoot集成Mybatis實(shí)現(xiàn)對(duì)多數(shù)據(jù)源訪問原理
注意?:SpringBoot
實(shí)際上連接多數(shù)據(jù)源的方式有很多種,也有很多成熟的技術(shù)選型,本文所提供的思路僅是為了幫助讀者加深SqlSessionFactoryBean
的理解和使用。
什么是多數(shù)據(jù)源
在現(xiàn)代軟件架構(gòu)中,多數(shù)據(jù)源
指的是應(yīng)用程序配置和連接到多個(gè)數(shù)據(jù)庫(kù)實(shí)例的能力。這種架構(gòu)允許應(yīng)用程序根據(jù)不同的業(yè)務(wù)需求、數(shù)據(jù)類型或性能要求,與多個(gè)獨(dú)立的數(shù)據(jù)庫(kù)環(huán)境交互。在實(shí)現(xiàn)上,每個(gè)數(shù)據(jù)源都有自己的連接池、事務(wù)管理和數(shù)據(jù)訪問對(duì)象。
上述專業(yè)定義可能有些晦澀難懂,其實(shí)你完全可以將多數(shù)據(jù)源
的概念可以類比于一個(gè)大型學(xué)校里有多個(gè)圖書館和圖書管理員的情況。每個(gè)圖書館(數(shù)據(jù)源)由不同的圖書管理員(數(shù)據(jù)庫(kù)管理系統(tǒng))負(fù)責(zé),管理著特定類型的書籍(數(shù)據(jù))。
比如,一個(gè)圖書館可能專注于科學(xué)書籍,而另一個(gè)專門存放文學(xué)作品。這樣的安排不僅提高了查找信息的效率——因?yàn)槊總€(gè)管理員都對(duì)自己的領(lǐng)域非常了解,同時(shí)還增強(qiáng)了安全性——因?yàn)榭梢詾椴煌愋偷臄?shù)據(jù)設(shè)置不同級(jí)別的保護(hù)。
隨著學(xué)校(業(yè)務(wù))的發(fā)展,可能需要新的圖書館來容納更多的書籍(數(shù)據(jù)),這時(shí)多圖書館的布局就顯得尤為重要??偠灾?code>多數(shù)據(jù)源在軟件應(yīng)用中的作用就像這些圖書館和圖書管理員一樣,確保數(shù)據(jù)的有效管理、安全和高效訪問。"
如上這張圖就反映了應(yīng)用中多數(shù)據(jù)源和單數(shù)據(jù)源之間的區(qū)別。接下來,我們就來分析在SpringBoot
應(yīng)用中,如何通過配置SqlSessionFactoryBean
來實(shí)現(xiàn)多數(shù)據(jù)源的連接。
環(huán)境搭建
工欲善其事必先利其器,開始動(dòng)手之前我們先來對(duì)構(gòu)建案例所需的環(huán)境進(jìn)行一個(gè)簡(jiǎn)單的介紹。后續(xù)案例所需的關(guān)鍵依賴如下:
SpringBoot
的構(gòu)建web
應(yīng)用的關(guān)鍵依賴:Spring-boot-starter-web
SpringBoot
整合Mybatis
的關(guān)鍵Starter:mybatis-spring-boot-starter
mysql
的jdbc
連接依賴:mysql-connector-java
- 數(shù)據(jù)連接池
druid
:druid-spring-boot-starter
項(xiàng)目整體結(jié)構(gòu)如下:
dao1
:數(shù)據(jù)源1
所對(duì)應(yīng)的數(shù)據(jù)Mapper
接口;dao2
:數(shù)據(jù)源2
所對(duì)應(yīng)的數(shù)據(jù)Mapper
接口;config
: 通過@Configuration
標(biāo)注的配置類信息。
除此之外,我們還需要準(zhǔn)備兩個(gè)數(shù)據(jù)源信息,在此筆者準(zhǔn)了如下所示的test_db
和test_db1
兩個(gè)數(shù)據(jù)庫(kù),其內(nèi)部均有一張t_user
的數(shù)據(jù)表。
t_user
數(shù)據(jù)表包含name
和type
兩個(gè)字段信息。
實(shí)戰(zhàn)雙數(shù)據(jù)源配置
在開始之前,我們先來簡(jiǎn)單回顧下SpringBoot
集成Mybatis
時(shí)在連接單數(shù)據(jù)源時(shí)是如何進(jìn)行配置的:
spring: datasource: username: root password: root # allowMultiQueries表示支持執(zhí)行;間隔的多個(gè)sql nullCatalogMeansCurrent=true返回指定庫(kù)涉及的表 jdbc-url: jdbc:mysql://127.0.0.1:3306/test_db?characterEncoding=utf8&useSSL=false&serverTimezone=UTC&tcpKeepAlive=true&autoReconnect=true&allowMultiQueries=true&nullCatalogMeansCurrent=true driver-class-name: com.mysql.cj.jdbc.Driver # 使用的連接池的類型 type: com.alibaba.druid.pool.DruidDataSource
在上述配置文件中,我們主要配置了如下內(nèi)容:
- 數(shù)據(jù)庫(kù)URL (
spring.datasource.url
): 這是數(shù)據(jù)庫(kù)服務(wù)器的地址和數(shù)據(jù)庫(kù)名。它通常包含協(xié)議(例如jdbc:mysql:
)、主機(jī)地址、端口號(hào)(對(duì)于MySQL,默認(rèn)是3306),以及要連接的數(shù)據(jù)庫(kù)名。例如:jdbc:mysql://localhost:3306/test_db
- 用戶名 (
spring.datasource.username
): 用于連接數(shù)據(jù)庫(kù)的用戶名。 - 密碼 (
spring.datasource.password
): 用于連接數(shù)據(jù)庫(kù)的密碼。 - 驅(qū)動(dòng)類名 (
spring.datasource.driver-class-name
): 這是JDBC
驅(qū)動(dòng)的完整類名,它用于告訴Spring Boot
應(yīng)用程序使用哪種數(shù)據(jù)庫(kù)。例如,對(duì)于MySQL
,通常是com.mysql.cj.jdbc.Driver
。
當(dāng)我們配置多數(shù)據(jù)源時(shí),配置文件需要做如下的修改:
spring: # 數(shù)據(jù)源1 primary: username: root password: root jdbc-url: jdbc:mysql://127.0.0.1:3306/test_db?characterEncoding=utf8&useSSL=false&serverTimezone=UTC&tcpKeepAlive=true&autoReconnect=true&allowMultiQueries=true&nullCatalogMeansCurrent=true driver-class-name: com.mysql.cj.jdbc.Driver # 使用的連接池的類型 type: com.alibaba.druid.pool.DruidDataSource # 數(shù)據(jù)源2 slave: username: root password: root jdbc-url: jdbc:mysql://127.0.0.1:3306/test_db1?characterEncoding=utf8&useSSL=false&serverTimezone=UTC&tcpKeepAlive=true&autoReconnect=true&allowMultiQueries=true&nullCatalogMeansCurrent=true driver-class-name: com.mysql.cj.jdbc.Driver type: com.alibaba.druid.pool.DruidDataSource
此時(shí),我們將之前配置文件中datasource
改為了primary
和 slave
,這樣SpringBoot
就不再會(huì)為我們?cè)O(shè)定默認(rèn)數(shù)據(jù)庫(kù)。與此同時(shí),我們將url
改為了jdbc-url
。這是因?yàn)?當(dāng)只有單個(gè)數(shù)據(jù)源時(shí),SpringBoot
會(huì)默認(rèn)將url
映射為 jdbc-url
進(jìn)行映射,進(jìn)而保證我們獲得數(shù)據(jù)源的成功注入。
此外,由于我們不再使用SpringBoot
的默認(rèn)配置來加載數(shù)據(jù)源,所以需要手動(dòng)設(shè)置的數(shù)據(jù)源的連接地址,如果不進(jìn)行修改,則會(huì)導(dǎo)致項(xiàng)目無法啟動(dòng),進(jìn)而出現(xiàn) jdbcUrl is required with driverClassName
的異常。
處理好配置文件后,我們需要構(gòu)建出DataSource
、SqlSessionFactory
從而實(shí)現(xiàn)對(duì)SqlSessionFactoryBean
的定制化配置,其具體配置如下:
@Configuration @MapperScan(basePackages = "com.example.dao1", sqlSessionFactoryRef = "sqlSessionFactory1") public class DataSource1Config { @Bean @ConfigurationProperties(prefix = "spring.primary") public DataSource dataSourcePrimary() { return DataSourceBuilder.create().build(); } @Bean public SqlSessionFactory sqlSessionFactory1() throws Exception { SqlSessionFactoryBean sessionFactoryBean = new SqlSessionFactoryBean(); sessionFactoryBean.setDataSource(dataSourcePrimary()); String locationPattern = "classpath*:/mapperPrimary/*.xml"; PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(); sessionFactoryBean.setMapperLocations(resolver.getResources(locationPattern)); return sessionFactoryBean.getObject(); } @Bean(name = "sqlSessionTemplate1") public SqlSessionTemplate sqlSessionTemplate1(@Qualifier("sqlSessionFactory1") SqlSessionFactory sqlSessionFactory) { return new SqlSessionTemplate(sqlSessionFactory); } }
當(dāng)我們期待使用Mybatis
操作多數(shù)據(jù)源時(shí),對(duì)于不同的數(shù)據(jù)源,我們都需要定義不同的Mapper
接口和XML
映射文件,以確保最終生成的Mapper
實(shí)現(xiàn)類可以操縱不同的數(shù)據(jù)源信息。所以,其中的dataSourcePrimary
就是為了加載dataSourcePrimary
指定的數(shù)據(jù)源信息,確保構(gòu)建的數(shù)據(jù)源最終連接到Primary
中指定的數(shù)據(jù)庫(kù)信息。而在sqlSessionFactory
的構(gòu)建中,則主要通過SqlSessionFactoryBean
來構(gòu)建出一個(gè)SqlSessionFactory
并注入容器,而在這一過程中需要設(shè)定Mapper
接口所對(duì)應(yīng)的配置文件。
slave
的配置可參考DataSource1Config
進(jìn)行配置,在此便不進(jìn)行贅述。接下來,我們來看下最終的效果:
@RestController @RequestMapping("/data") @Slf4j public class DataSourceController { @Autowired private User1Mapper userMapper; @Autowired private User2Mapper user2Mapper; @GetMapping("/get-user1/{name}") public User getUserFromTestDb(@PathVariable("name") String userName) { return userMapper.selectUser(userName); } @GetMapping("/get-user2/{name}") public User getUserFromTestDb2(@PathVariable("name") String userName) { return user2Mapper.selectUser(userName); } }
getUserFromTestDb
用于從數(shù)據(jù)源test_db
獲取數(shù)據(jù)getUserFromTestDb2
用于從數(shù)據(jù)源test_db1
獲取數(shù)據(jù)
最終效果如下:
訪問數(shù)據(jù)源1
訪問數(shù)據(jù)源2
總結(jié)
接下來,我們對(duì)上述程序用到的組件進(jìn)行一個(gè)簡(jiǎn)要的總結(jié)和回顧
數(shù)據(jù)源(
DataSource
)。數(shù)據(jù)源是數(shù)據(jù)庫(kù)連接的工廠。在Spring
中,DataSource
對(duì)象負(fù)責(zé)提供數(shù)據(jù)庫(kù)連接。當(dāng)配置多個(gè)數(shù)據(jù)源時(shí),每個(gè)數(shù)據(jù)源都對(duì)應(yīng)不同的數(shù)據(jù)庫(kù)連接信息。例如,一個(gè)數(shù)據(jù)源可能連接到數(shù)據(jù)庫(kù)test_db
,而另一個(gè)連接到數(shù)據(jù)庫(kù)test_db1
。Mybatis的SqlSessionFactory
。SqlSessionFactory
是Mybatis
中的一個(gè)核心組件,它負(fù)責(zé)創(chuàng)建SqlSession
。SqlSession
提供了執(zhí)行SQL
命令、獲取映射器和管理事務(wù)的方法。在配置多個(gè)數(shù)據(jù)源的情況下,每個(gè)數(shù)據(jù)源都需要有對(duì)應(yīng)的SqlSessionFactory
,以確保SQL
操作能夠針對(duì)正確的數(shù)據(jù)庫(kù)執(zhí)行。@MapperScan
注解的使用。該注解用于指定哪些包中的接口應(yīng)該被Mybatis
識(shí)別為映射器(Mapper
)。在多數(shù)據(jù)源配置中,可以使用不同的@MapperScan
注解來指定不同數(shù)據(jù)源的映射器。
更進(jìn)一步,SpringBoot
集成Mybatis
實(shí)現(xiàn)多數(shù)據(jù)源的基本流程如下:
- 為每個(gè)數(shù)據(jù)源定義獨(dú)立的配置,包括
DataSource、SqlSessionFactory
。 - 使用
@MapperScan
為每個(gè)數(shù)據(jù)源指定Mapper
接口的位置。 - 將配置好的
SqlSessionFactory
交由SpringBoot
容器進(jìn)行管理
這樣,當(dāng)應(yīng)用程序運(yùn)行時(shí),只需要注入不同數(shù)據(jù)源對(duì)應(yīng)的Mapper
即可訪問不同的數(shù)據(jù)庫(kù),而無需擔(dān)心數(shù)據(jù)源之間的沖突和干擾。
最后,希望本文對(duì)你對(duì)有助于加深理解SpringBoot
集成Mybatis
的原理。
以上就是SpringBoot集成Mybatis實(shí)現(xiàn)對(duì)多數(shù)據(jù)源訪問原理的詳細(xì)內(nèi)容,更多關(guān)于SpringBoot Mybatis多數(shù)據(jù)源訪問的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
- MyBatisPuls多數(shù)據(jù)源操作數(shù)據(jù)源偶爾報(bào)錯(cuò)問題
- Mybatis-plus配置多數(shù)據(jù)源,連接多數(shù)據(jù)庫(kù)方式
- MyBatis-Plus多數(shù)據(jù)源的示例代碼
- Seata集成Mybatis-Plus解決多數(shù)據(jù)源事務(wù)問題
- 詳解SpringBoot Mybatis如何對(duì)接多數(shù)據(jù)源
- Mybatis操作多數(shù)據(jù)源的實(shí)現(xiàn)
- 一文搞懂MyBatis多數(shù)據(jù)源Starter實(shí)現(xiàn)
- Mybatis-plus多數(shù)據(jù)源配置的兩種方式總結(jié)
- MyBatis-Plus 集成動(dòng)態(tài)多數(shù)據(jù)源的實(shí)現(xiàn)示例
- Mybatis-Plus的多數(shù)據(jù)源你了解嗎
- mybatis-flex實(shí)現(xiàn)多數(shù)據(jù)源操作
相關(guān)文章
Struts2學(xué)習(xí)筆記(2)-路徑問題解決
本文主要介紹Struts2的路徑問題,盡量不要使用相對(duì)路徑,使用相對(duì)路徑會(huì)讓路徑問題變得很繁瑣很麻煩,推薦使用絕對(duì)路徑,希望能給大家做一個(gè)參考。2016-06-06Spring常用注解及自定義Filter的實(shí)現(xiàn)
這篇文章主要介紹了Spring常用注解及自定義Filter的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-08-08Java實(shí)現(xiàn)將數(shù)據(jù)導(dǎo)出為Word文檔的方法步驟
我們?cè)陂_發(fā)一些系統(tǒng)的時(shí)候,例如OA系統(tǒng),經(jīng)常能遇到將審批單數(shù)據(jù)導(dǎo)出為word和excel文檔的需求,導(dǎo)出為excel是比較簡(jiǎn)單的,但是word文檔的格式不像表格那樣可以輕松的定位,所以本文給大家介紹了Java怎樣實(shí)現(xiàn)將數(shù)據(jù)導(dǎo)出為Word文檔,需要的朋友可以參考下2025-01-01Spring Cloud Gateway不同頻率限流的解決方案(每分鐘,每小時(shí),每天)
SpringCloud Gateway 是 Spring Cloud 的一個(gè)全新項(xiàng)目,它旨在為微服務(wù)架構(gòu)提供一種簡(jiǎn)單有效的統(tǒng)一的 API 路由管理方式。這篇文章主要介紹了Spring Cloud Gateway不同頻率限流(每分鐘,每小時(shí),每天),需要的朋友可以參考下2020-10-10Spring?boot2.0?實(shí)現(xiàn)日志集成的方法(2)
這篇文章主要介紹了Spring?boot2.0?實(shí)現(xiàn)日志集成的方法,上一章講解了spring?boot日志簡(jiǎn)單集成,這篇我們將日志進(jìn)行分類,常規(guī)日志、異常日志、監(jiān)控日志等,需要將日志輸出到不同的文件,具體內(nèi)容需要的小伙伴可以參考一下2022-04-04form表單回寫技術(shù)java實(shí)現(xiàn)
這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)form表單回寫技術(shù)的相關(guān)資料,需要的朋友可以參考下2016-04-04背包問題-動(dòng)態(tài)規(guī)劃java實(shí)現(xiàn)的分析與代碼
這篇文章主要給大家介紹了關(guān)于背包問題動(dòng)態(tài)規(guī)劃java實(shí)現(xiàn)的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-12-12