1. 业务需求
1.1. 场景说明
多数据源适用于多种场景:纯粹多库、读写分离、一主多从、混合模式等等。
在这里我们模拟一个纯粹多库的场景,其他场景类似。我们创建两个库(一个为Oracle数据库,一个为MariaDB数据库),Oracle中有一张表 mpa_test, 而 MariaDB 中有一张表 mpb_test 通过一个测试用例分别获取表中数据,如果获取到说明多库模拟成功。
1.2. 业务逻辑
1.3. 数据库模拟数据
-- Oracle
CREATE TABLE mpa_account (acc_num INT NOT NULL,
acc_name VARCHAR2(20),
phone_no INT NOT NULL,
update_time DATE DEFAULT SYSDATE NOT NULL ,
CONSTRAINT pk_mpa_account PRIMARY KEY(acc_num));
INSERT INTO mpa_account (acc_num,acc_name,phone_no) VALUES(11,'Liucc11',13100000011);
INSERT INTO mpa_account (acc_num,acc_name,phone_no) VALUES(12,'Liucc12',13100000012);
INSERT INTO mpa_account (acc_num,acc_name,phone_no) VALUES(13,'Liucc13',13100000013);
COMMIT;
-- MariaDB
DROP TABLE IF EXISTS mpb_account;
CREATE TABLE mpb_account (acc_num INT NOT NULL,
acc_name VARCHAR(20),
phone_no NUMERIC(11) NOT NULL,
update_time DATETIME DEFAULT CURRENT_TIMESTAMP() NOT NULL ,
PRIMARY KEY(acc_num));
INSERT INTO mpb_account (acc_num,acc_name,phone_no) VALUES(21,'Liucc21',18900000021);
INSERT INTO mpb_account (acc_num,acc_name,phone_no) VALUES(22,'Liucc22',18900000022);
INSERT INTO mpb_account (acc_num,acc_name,phone_no) VALUES(23,'Liucc23',18900000023);
COMMIT;
2. 代码实现
2.1. 创建目录
2.2. 引入依赖
-
MyBatis Plus(包含了 mybatis-plus-extension)
mybatis-plus-boot-starter -
动态数据源:Dynamic Datasource Spring Boot Starter
dynamic-datasource-spring-boot-starter -
lombok:Project Lombok
lombok -
oracle连接驱动: Ojdbc8
Ojdbc8 -
MariaDB连接驱动:MariaDB Java Client
mariadb-java-client -
Orai18n:Orai18n
Orai18n
2.3. 配置日志输出方式
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.log4j2.Log4j2Impl
2.4. 配置数据源
创建 application.yml 文件,编写数据库访问方式信息:
spring:
datasource:
dynamic:
primary: oracle
strict: false
datasource:
oracle:
driver-class-name: oracle.jdbc.driver.OracleDriver
url: jdbc:oracle:thin:@192.168.5.103/etdb2
username: study
password: study
mariadb:
drive-class-name: org.mariadb.jdbc.Driver
url: jdbc:mariadb://192.168.4.43:6006/study
username: study
password: study
2.5. 生成代码
利用插件 MaBatisX 生成代码,参见: http://dba.qishuo.xin/?p=1395
2.6. 添加@DS注解
@DS注解先必须要写在mapper上,不然数据源无法切换。报如下错误:
其次@DS 可以注解在方法上和类上。如果同时存在,方法注解优先于类上注解。强烈建议注解在 service 实现或 mapper 接口方法上。
例如:
- Mapper
@Repository
@DS("oracle")
public interface MpaAccountMapper extends BaseMapper<MpaAccount> {
}
@Repository
@DS("mariadb")
public interface MpbAccountMapper extends BaseMapper<MpbAccount> {
}
- service
// Service
public interface MpaAccountService extends IService<MpaAccount> {
}
public interface MpbAccountService extends IService<MpbAccount> {
}
// Service Implement
@Service
@DS("oracle")
public class MpaAccountServiceImpl extends ServiceImpl<MpaAccountMapper, MpaAccount>
implements MpaAccountService{
}
@Service
@DS("mariadb")
public class MpbAccountServiceImpl extends ServiceImpl<MpbAccountMapper, MpbAccount>
implements MpbAccountService{
}
2.7. 在SprintBoot主启动器中添加 MapperScan
@MapperScan("com.hz571.easytong_etl.mapper")
2.8. 测试类
@Test
public void testMoreDS(){
System.out.println(mpaAccountMapper.selectById(11));
System.out.println(mpbAccountMapper.selectById(21));
}
3. 注意事项
- 不能使用事务,否则数据源不会切换,使用的还是是第一次加载的数据源 (待确认)
- 删除 操作多数据源的方法或者类、接口 上的 注解 @Transactional(rollbackFor = Exception.class) 即可。
- 第一次加载的数据源之后,第二次(第三次...)操作其它数据源,如果数据源不存在,使用的还是第一次加载的数据源
- 数据源名称最好不要包含下滑线,下滑线的数据源切换不了
附录A
A.1. 参考:
- MyBatis-Plus多数据源配置
https://blog.csdn.net/m0_67401606/article/details/123495774
https://baomidou.com/pages/a61e1b/ (官方)