實現(xiàn)多數(shù)據(jù)源的方式有很多種,本例采用com.baomidou(MybatisPlus擁有者旗下)包下的dynamic-datasource來實現(xiàn)。
1. 具體步驟
1.1 添加依賴
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
<version>2.5.4</version>
</dependency>
1.2 配置數(shù)據(jù)源,mybatis-plus支持各種數(shù)據(jù)源的配置
配置一個默認(rèn)庫master视译,兩個子庫slave_1,slave_2挪哄,要注意的是如果用的mysql數(shù)據(jù)庫私沮,不需要設(shè)置driver-class-name,框架會自身自動補全這部分內(nèi)容香璃,如果用的oracle還是要去修改的这难。
spring:
datasource:
dynamic:
primary: master #設(shè)置默認(rèn)的數(shù)據(jù)源或者數(shù)據(jù)源組,默認(rèn)值即為master
strict: false #設(shè)置嚴(yán)格模式,默認(rèn)false不啟動. 啟動后在未匹配到指定數(shù)據(jù)源時候會拋出異常,不啟動則使用默認(rèn)數(shù)據(jù)源.
datasource:
master:
url: jdbc:mysql://xx.xx.xx.xx:3306/dynamic
username: root
password: 123456
driver-class-name: com.mysql.jdbc.Driver # 3.2.0開始支持SPI可省略此配置
slave_1:
driver-class-name: oracle.jdbc.OracleDriver
url: jdbc:oracle:thin:@192.168.7.88:1521:db
username: test
password: test
#Oracle需要打開注釋
validation-query: SELECT 1 FROM DUAL
slave_2:
url: ENC(xxxxx) # 內(nèi)置加密,使用請查看詳細(xì)文檔
username: ENC(xxxxx)
password: ENC(xxxxx)
driver-class-name: com.mysql.jdbc.Driver
schema: db/schema.sql # 配置則生效,自動初始化表結(jié)構(gòu)
data: db/data.sql # 配置則生效,自動初始化數(shù)據(jù)
continue-on-error: true # 默認(rèn)true,初始化失敗是否繼續(xù)
separator: ";" # sql默認(rèn)分號分隔符
1.3 通過注解方式注解到類或者方法上
項目中使用@DS注解來切換數(shù)據(jù)源,@DS使用需要注意的幾點:
- @DS(注解不能直接用于mapper類上只能用在service層的類或方法上
- @DS可以注解在方法或類上葡秒,同時存在使用就近原則姻乓,方法上注解優(yōu)于類上注解
- @DS和@Transactional(rollbackFor = Exception.class)不要同時使用,會導(dǎo)致切換數(shù)據(jù)源失效
@Service("LdService")
@DS("slave_1")
public class LdServiceImpl implements LdService {
}
也可使用DynamicDataSourceContextHolder.push(dsKey);方法來切換數(shù)據(jù)源眯牧,dsKey:你自己要切換的數(shù)據(jù)源名稱蹋岩,和@DS括號中的一樣
2.切換數(shù)據(jù)源失效場景
(1)@DS中寫的是錯誤的數(shù)據(jù)源符號,如oracle寫成了orcale,雖然一個字符之差学少,而且也很難察覺剪个,這樣如果配置了默認(rèn)數(shù)據(jù)源則會使用默認(rèn)的數(shù)據(jù)源,否則會拋出異常版确。
(2)@DS和@Transactional(rollbackFor = Exception.class)不要同時使用扣囊,若同時使用會將數(shù)據(jù)源直接交給spring來管理,
這也是切換數(shù)據(jù)源經(jīng)常失效場景之一绒疗,若需要使用事務(wù)侵歇,則要考慮分布式事務(wù),常用的分布式事務(wù)框架有Seata忌堂、TX-LCN等等 盒至。注意:其他多數(shù)據(jù)源的方法也是如此。
(3)方法內(nèi)部的相互調(diào)用士修,如:
public UserService {
@DS("first")
public void test1() {
// do something
test2();
}
@DS("second")
public void test2() {
// do something
}
}
部調(diào)用 userservice.test1() 在執(zhí)行到 test2()中的時候也是不能切換數(shù)據(jù)源的枷遂,解決方式為把test2()方法提到另外一個service,單獨調(diào)用