SpringBoot整合Mybatis-Plus多數(shù)據(jù)源
一、前言
隨著業(yè)務(wù)的不斷擴(kuò)展和復(fù)雜度的增加,我們在開發(fā)過程中往往需要訪問多個數(shù)據(jù)庫。比如:我們可能需要同時訪問主數(shù)據(jù)庫和從數(shù)據(jù)庫,或者訪問多個獨立的數(shù)據(jù)庫來處理不同的業(yè)務(wù)邏輯。這時候,我們就需要使用多數(shù)據(jù)源來實現(xiàn)對多個數(shù)據(jù)庫的操作。
MyBatis-Plus則是一個優(yōu)秀的ORM框架,它為我們封裝了大量的數(shù)據(jù)庫操作細(xì)節(jié),簡化了我們的開發(fā)工作,同時也提供了多數(shù)據(jù)源方案。
- dynamic-datasource 開源文檔付費(fèi),屬于組織參與者小鍋蓋發(fā)起的項目。
- mybatis-mate 企業(yè)級付費(fèi)授權(quán),資料文檔免費(fèi)。
今天我們以第一種方案來具體說一下怎么實現(xiàn)!
MyBatis-Plus多數(shù)據(jù)源官網(wǎng):https://baomidou.com/pages/a61e1b/#dynamic-datasource。
二、簡單搭建測試
1、準(zhǔn)備工作
我們先把一些使用的版本列舉一下,方便大家看!
- Spring Boot:2.7.4
- dynamic-datasource:3.5.1
- mybatis-plus:3.5.1
數(shù)據(jù)庫方面這里就不演示了,我們準(zhǔn)備好兩個mysql數(shù)據(jù)庫:
2、添加依賴
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.24</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
<version>3.5.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Druid -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.15</version>
</dependency>
<!-- mysql -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- mybatis-plus -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.1</version>
</dependency>
3、yml配置
spring:
datasource:
#使用阿里的Druid
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
dynamic:
primary: master #設(shè)置默認(rèn)的數(shù)據(jù)源或者數(shù)據(jù)源組,默認(rèn)值即為master
strict: false #嚴(yán)格匹配數(shù)據(jù)源,默認(rèn)false. true未匹配到指定數(shù)據(jù)源時拋異常,false使用默認(rèn)數(shù)據(jù)源
datasource:
master:
url: jdbc:mysql://127.0.0.1:3306/test?serverTimeznotallow=Asia/Shanghai
username: root
password:
slave_1:
url: jdbc:mysql://127.0.0.1:3306/test1?serverTimeznotallow=Asia/Shanghai
username: root
password:
「補(bǔ)充:」
可以繼續(xù)多種模式,咱們以簡單的進(jìn)行演示!
# 多主多從 純粹多庫(記得設(shè)置primary) 混合配置
spring: spring: spring:
datasource: datasource: datasource:
dynamic: dynamic: dynamic:
datasource: datasource: datasource:
master_1: mysql: master:
master_2: oracle: slave_1:
slave_1: sqlserver: slave_2:
slave_2: postgresql: oracle_1:
slave_3: h2: oracle_2:
4、實體類
@Data
public class Test {
@TableId
private Integer id;
private String name;
private Integer age;
private LocalDateTime time;
private LocalDateTime createdAt;
}
5、多數(shù)據(jù)源配置Mapper
使用 @DS 切換數(shù)據(jù)源。@DS 可以注解在方法上或類上,同時存在就近原則 方法上注解 優(yōu)先于 類上注解。
注解 | 結(jié)果 |
沒有@DS | 默認(rèn)數(shù)據(jù)源 |
@DS("dsName") | dsName可以為組名也可以為具體某個庫的名稱 |
public interface TestDbMapper extends BaseMapper<Test> {
}
@DS("slave_1")
public interface TestDb2Mapper extends BaseMapper<Test> {
}
注意:
這里@DS
可以添加在service中的方法上來切換數(shù)據(jù)源,也可以像小編一樣加在Mapper接口上!
他們各有優(yōu)缺點,我們需要權(quán)衡利弊進(jìn)行選擇:
如果一個Service只需要使用一個數(shù)據(jù)源,或者多個Service方法都需要使用相同的數(shù)據(jù)源,則建議將@DS注解添加到Mapper接口或XML文件上;如果需要根據(jù)不同的業(yè)務(wù)場景動態(tài)切換數(shù)據(jù)源,則可以選擇在Service方法上使用@DS注解。
當(dāng)然還有一種情況,一個service方法操作不同的數(shù)據(jù)源,表結(jié)構(gòu)一樣的話可以使用一個mapper。
在service內(nèi)部進(jìn)行切換,我們看到官方注釋,「非必要不要這么使用」!
// 設(shè)置當(dāng)前線程數(shù)據(jù)源 如非必要不要手動調(diào)用,調(diào)用后確保最終清除
DynamicDataSourceContextHolder.push("slave_1");
// 獲得當(dāng)前線程數(shù)據(jù)源
DynamicDataSourceContextHolder.peek();
// 強(qiáng)制清空本地線程 防止內(nèi)存泄漏,如手動調(diào)用了push可調(diào)用此方法確保清除
DynamicDataSourceContextHolder.poll();
完整代碼塊:
@Override
public Result saveTest() {
Test test = new Test();
test.setId(1993);
test.setName("add方法");
// 切換指定數(shù)據(jù)源
DynamicDataSourceContextHolder.push("slave_1");
testDbMapper.insert(test);
//查看當(dāng)前數(shù)據(jù)源
log.info(DynamicDataSourceContextHolder.peek());
//移除數(shù)據(jù)源,恢復(fù)master數(shù)據(jù)源
DynamicDataSourceContextHolder.clear();
testDbMapper.insert(test);
return Result.success("222");
}
數(shù)據(jù)庫展示:
6、測試
我們還是以把@DS放在mapper類上來進(jìn)行演示:
@Autowired
private TestDbMapper testDbMapper;
@Autowired
private TestDb2Mapper testDb2Mapper;
@Override
public Result saveTest() {
Test test = new Test();
test.setId(1994);
test.setName("add方法");
testDbMapper.insert(test);
testDb2Mapper.insert(test);
return Result.success("222");
}
數(shù)據(jù)庫正常保存到兩個庫,測試通過!
7、事務(wù)問題
在使用多數(shù)據(jù)源的同時,也帶來了一下事務(wù)問題,如果一個方法添加了@Transactional(rollbackFor = Exception.class)事務(wù),默認(rèn)查詢只會從默認(rèn)庫來查詢。
這個問題是要解決的,這里小編給幾個思路大家可以試一下!
- Spring Boot提供了一個基于Atomikos的JTA實現(xiàn)。
- 可以配置多個DataSourceTransactionManager進(jìn)行管理事務(wù)。
能分開系統(tǒng)來進(jìn)行數(shù)據(jù)源的隔離,需要查詢數(shù)據(jù)可以使用feign來獲??!小編還沒在企業(yè)中使用多數(shù)據(jù)源,缺乏一下關(guān)于事務(wù)方面的分享,大家有想法或者熟悉的可以留言分享一下自己的經(jīng)驗!
三、總結(jié)
希望這篇博客能夠幫助讀者更好地理解和掌握Spring Boot和MyBatis-Plus多數(shù)據(jù)源的使用方法,并應(yīng)用到實際項目中去。同時,也提醒讀者在使用多數(shù)據(jù)源的時候要注意事項,比如事務(wù)管理、連接池配置等,以確保系統(tǒng)的穩(wěn)定性和可靠性。