系列文章目錄
MyBatis緩存原理
Mybatis plugin 的使用及原理
MyBatis+Springboot 啟動到SQL執行全流程
數據庫操作不再困難,MyBatis動態Sql標簽解析
從零開始,手把手教你搭建Spring Boot后臺工程并說明
Spring框架與SpringBoot的關聯與區別
Spring監聽器用法與原理詳解
Spring事務暢談 —— 由淺入深徹底弄懂 @Transactional注解
實戰指南,SpringBoot + Mybatis 如何對接多數據源
- 系列文章目錄
- 一、數據源的定義
- 二、單數據源配置
- 三、如何配置多數據源
- 1. 工程層級調整
- 2. Spring項目配置
- 3. 會話配置
- 4. 事務管理器
- 四、驗證
- 總結
在我們開發一些具有綜合功能的項目時,往往會碰到一種情況,需要同時連接多個數據庫,這個時候就需要用到多數據源的設計。而Spring 與 Myabtis 其實做了多數據源的適配,只需少許改動即可對接多數據源。本期我們就貼近實戰,以一個單數據源的Demo為例,講述將其改為多數據源項目的過程,希望大家能有所體會
📕作者簡介:戰斧,從事金融IT行業,有著多年一線開發、架構經驗;愛好廣泛,樂于分享,致力于創作更多高質量內容
📗本文收錄于 Spring全家桶 專欄,有需要者,可直接訂閱專欄實時獲取更新
📘高質量專欄 云原生、RabbitMQ、Spring全家桶 等仍在更新,歡迎指導
📙Zookeeper Redis kafka docker netty等諸多框架,以及架構與分布式專題即將上線,敬請期待
一、數據源的定義
數據源(Data Source)是指數據存儲的地方,大多數情況是指數據庫,不過文件服務器、傳感器、API等也能算數據源,主要是提供了對數據的訪問和操作。數據源中存儲了所有建立數據庫連接的信息。就像通過指定文件名稱可以在文件系統中找到文件一樣,通過提供正確的數據源名稱,你可以找到相應的數據庫連接
二、單數據源配置
因為SpringBoot對數據源有著高度的默認配置,只配置一個數據源時,該數據源會被作為默認,所以對接單數據源其實是非常簡單的。如果你的工程采用的yaml格式配置文件,我們僅需做如下配置:
spring:#數據庫連接配置datasource:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://127.0.0.1:3306/springtestusername: rootpassword: root
如果是采用properties配置文件的也是一樣的:
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/springtest
spring.datasource.username=root
spring.datasource.password=root
三、如何配置多數據源
1. 工程層級調整
我們以曾經搭建的工程為原始模板,進行對接多數據源的操作。沒看過的可以點此查看: 從零開始,手把手教你搭建Spring Boot后臺工程并說明
因為僅變動數據源,所以我們不改動其他層級,僅僅將 mapper 拆為 mapper1 與 mapper2 兩部分
2. Spring項目配置
然后我們需要在 application.properties 或者 application.yml 中定義多個數據源:
spring:#數據庫連接配置datasource1:driver-class-name: com.mysql.cj.jdbc.Driverjdbc-url: jdbc:mysql://127.0.0.1:3306/springtest2username: rootpassword: rootdatasource2:driver-class-name: com.mysql.cj.jdbc.Driverjdbc-url: jdbc:mysql://127.0.0.1:3306/springtestusername: rootpassword: root
這里有兩個細節需要注意:
- 因為我們決定使用雙數據源,所以把數據源的連接配置改成了
datasource1
和datasource2
。而不再保留datasource
,這樣SpringBoot就不再會為我們設定默認數據庫 - 因為我們目前采用的 springBoot2.5.2,默認的連接池為
Hikari
,該連接池數據源的地址字段為jdbc-url
而非url
。在只有單個數據源時,SpringBoot走默認數據源邏輯為我們把url
與jdbc-url
進行映射,保證我們獲得數據源。此時我們自己設置的數據源沒有進行映射處理,就需要保證字段符合Hikari
的要求。否則會出現java.lang.IllegalArgumentException: jdbcUrl is required with driverClassName
異常
3. 會話配置
僅有配置文件可不行,接下來,我們需要在代碼中讀取到配置,并建立兩個數據源。如下,每個數據源都有隔離的mapper接口、xml文件、會話工廠及會話模板
第一個數據源 如下(示例):
@Configuration
@MapperScan(basePackages = "com.zhanfu.springboot.demo.mapper1", sqlSessionFactoryRef = "sqlSessionFactory1")
public class DataSource1Config {@Bean@ConfigurationProperties(prefix = "spring.datasource1")public DataSource dataSource1() {return DataSourceBuilder.create().build();}@Beanpublic SqlSessionFactory sqlSessionFactory1() throws Exception {SqlSessionFactoryBean sessionFactoryBean = new SqlSessionFactoryBean();sessionFactoryBean.setDataSource(dataSource1());String locationPattern = "classpath*:/mapper1/*.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);}
}
配置第二個數據源 DataSource2Config
@Configuration
@MapperScan(basePackages = "com.zhanfu.springboot.demo.mapper2", sqlSessionFactoryRef = "sqlSessionFactory2")
public class DataSource2Config {@Bean@ConfigurationProperties(prefix = "spring.datasource2")public DataSource dataSource2() {return DataSourceBuilder.create().build();}@Beanpublic SqlSessionFactory sqlSessionFactory2() throws Exception {SqlSessionFactoryBean sessionFactoryBean = new SqlSessionFactoryBean();sessionFactoryBean.setDataSource(dataSource2());String locationPattern = "classpath*:/mapper2/*.xml";PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();sessionFactoryBean.setMapperLocations(resolver.getResources(locationPattern));return sessionFactoryBean.getObject();}@Bean(name = "sqlSessionTemplate2")public SqlSessionTemplate sqlSessionTemplate2(@Qualifier("sqlSessionFactory2") SqlSessionFactory sqlSessionFactory) {return new SqlSessionTemplate(sqlSessionFactory);}@Bean(name = "productMapper")public ProductMapper mapper2(@Qualifier("sqlSessionTemplate2") SqlSessionTemplate sqlSessionTemplate) throws Exception {return sqlSessionTemplate.getMapper(ProductMapper.class);}
}
4. 事務管理器
為兩個數據源分別配置自己的事務管理器,如果你的項目里通篇沒有方法級別的事務(一個SQL就是一個事務),那不設置這個也不影響,否則還是建議加上。
@Configuration
public class TransactionManagerConfig {@Autowiredprivate DataSource dataSource1;@Autowiredprivate DataSource dataSource2;@Beanpublic PlatformTransactionManager txManager1() {return new DataSourceTransactionManager(dataSource1);}@Beanpublic PlatformTransactionManager txManager2() {return new DataSourceTransactionManager(dataSource2);}
}
四、驗證
我們把兩張表拆進兩個庫中,以兩個庫模擬兩個數據源,使得程序可以同時連接兩個庫
瀏覽器輸入 http://127.0.0.1:8080/user/findall 查詢接口成功
再在瀏覽器輸入 http://127.0.0.1:8080/product/findall 查詢第二個庫的數據亦成功返回
這樣我們就完成了一個工程同時連接兩個數據源。
總結
經過上述的操作,我們已經成功把項目對接了多數據源。當然,方案肯定不止這一種,后續圍繞該問題,我們還會講解其他方式。但不論是什么方式,主旨都是加深大家對SpringBoot 和 Mybatis的理解,我們曾經梳理過全流程,但只是蜻蜓點水帶大家看一遍大體輪廓,并不足以讓你精通,后面本專欄將繼續深入講解