SpringBoot结合MyBatis实现多数据源配置
一、前提条件
1.1、环境准备
SpringBoot框架实现多数据源操作,首先需要搭建Mybatis的运行环境。
由于是多数据源,也就是要有多个数据库,所以,我们创建两个测试数据库,分别是:【sp-demo01】和【sp-demo02】,如下图所示:

具体SQL代码:
- 创建【sp-demo01】数据库。
-- 创建数据库
CREATE DATABASE sp-demo01;
-- ----------------------------
-- Table structure for t_emp
-- ----------------------------
DROP TABLE IF EXISTS `t_emp`;
CREATE TABLE `t_emp` (
`emp_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '员工ID',
`emp_name` varchar(255) NOT NULL COMMENT '员工姓名',
`age` int(11) DEFAULT NULL COMMENT '年龄',
`dept_id` int(11) NOT NULL COMMENT '部门ID',
PRIMARY KEY (`emp_id`)
) ENGINE=InnoDB AUTO_INCREMENT=3002 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of t_emp
-- ----------------------------
INSERT INTO `t_emp` VALUES ('2001', 'Lucy', '21', '1002');
INSERT INTO `t_emp` VALUES ('3001', 'Tom', '25', '1001');
- 创建【sp-demo02】数据库。
-- 创建数据库
CREATE DATABASE sp-demo02;
-- ----------------------------
-- Table structure for t_dept
-- ----------------------------
DROP TABLE IF EXISTS `t_dept`;
CREATE TABLE `t_dept` (
`dept_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '部门ID',
`dept_name` varchar(255) NOT NULL COMMENT '部门名称',
`desc` varchar(255) DEFAULT NULL COMMENT '描述',
PRIMARY KEY (`dept_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1003 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of t_dept
-- ----------------------------
INSERT INTO `t_dept` VALUES ('1001', '研发部', '编写程序');
INSERT INTO `t_dept` VALUES ('1002', '测试部', '寻找bug');
1.2、如何配置
MyBatis框架中,提供了一个**【@MapperScan】注解,该注解作用是指定mapper接口所在的路径,并且这个注解中,也可以指定使用哪个【SqlSessionFactory】对象,只需要通过该注解的【sqlSessionFactoryRef】**属性即可实现。
这里的SqlSessionFactory就相当于是一个数据库,如果我们要配置多数据源,那就相当于是要在工程里面创建多个SqlSessionFactory对象,然后再使用的时候指定具体的SqlSessionFactory对象即可。

配置数据源,需要创建三个对象,分别是下面三个:
- 第一个对象:创建DataSource对象。
- 第二个对象:创建SqlSessionFactory对象。
- 第三个对象:创建SqlSessionTmplate对象。
知道了这个知识,那就可以进行多数据源配置啦。
二、多数据源配置
这里,我们就创建两个数据源作为测试案例,两个数据源分别叫做【MasterDataSource】和【SlaveDataSource】。
2.1、创建数据源配置类
(1)创建Master配置类
在工程中,创建一个【MasterDataSourceConfig】配置类,代码如下所示:
package com.spring.boot.demo.config;
import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.mybatis.spring.boot.autoconfigure.SpringBootVFS;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import javax.sql.DataSource;
/**
* @author Js
* @version 1.0.0
* @Date: 2023/09/06 19:16:30
* @Description
*/
@MapperScan(
basePackages = "com.spring.boot.demo.master.mapper",
sqlSessionFactoryRef = "masterSqlSessionFactory",
sqlSessionTemplateRef = "masterSqlSessionTemplate"
)
@Configuration
public class MasterDataSourceConfig {
// 默认指定 master 作为主数据源
@Primary
// 注入数据源
@Bean("masterDataSource")
// 指定 master 数据源的配置信息前缀
@ConfigurationProperties(prefix = "spring.datasource.master")
public DataSource masterDataSource() {
// 手动创建 Druid 数据源对象
return DruidDataSourceBuilder.create().build();
}
// 创建 SqlSessionFactory 对象
@Bean("masterSqlSessionFactory")
public SqlSessionFactory masterSqlSessionFactory(@Qualifier("masterDataSource") DataSource masterDataSource) throws Exception {
// 创建 SqlSessionFactoryBean 对象
SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
// 设置数据源
factoryBean.setDataSource(masterDataSource);
// 设置 mapper 映射文件路径
PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
factoryBean.setMapperLocations(resolver.getResources("classpath:mappers/master/**/*.xml"));
// 设置 VFS
factoryBean.setVfs(SpringBootVFS.class);
// 返回 SqlSessionFactory 对象
return factoryBean.getObject();
}
// 创建 SqlSessionTemplate 对象
@Bean("masterSqlSessionTemplate")
public SqlSessionTemplate masterSqlSessionTemplate(@Qualifier("masterSqlSessionFactory") SqlSessionFactory masterSqlSessionFactory) {
// 创建 SqlSessionTemplate 对象
return new SqlSessionTemplate(masterSqlSessionFactory);
}
}
(2)创建Slave配置类
在工程中,创建一个【SlaveDataSourceConfig】配置类,代码如下所示:
package com.spring.boot.demo.config;
import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.mybatis.spring.boot.autoconfigure.SpringBootVFS;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import javax.sql.DataSource;
/**
* @author Js
* @version 1.0.0
* @Date: 2023/09/06 19:30:45
* @Description
*/
@MapperScan(
basePackages = "com.spring.boot.demo.slave.mapper",
sqlSessionFactoryRef = "slaveSqlSessionFactory",
sqlSessionTemplateRef = "slaveSqlSessionTemplate"
)
@Configuration
public class SlaveDataSourceConfig {
// 注入数据源
@Bean("slaveDataSource")
// 指定 slave 数据源的配置信息前缀
@ConfigurationProperties(prefix = "spring.datasource.slave")
public DataSource slaveDataSource() {
// 手动创建 Druid 数据源对象
return DruidDataSourceBuilder.create().build();
}
// 创建 SqlSessionFactory 对象
@Bean("slaveSqlSessionFactory")
public SqlSessionFactory slaveSqlSessionFactory(@Qualifier("slaveDataSource") DataSource slaveDataSource) throws Exception {
// 创建 SqlSessionFactoryBean 对象
SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
// 设置数据源
factoryBean.setDataSource(slaveDataSource);
// 设置 mapper 映射文件路径
PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
factoryBean.setMapperLocations(resolver.getResources("classpath:mappers/slave/**/*.xml"));
// 设置 VFS
factoryBean.setVfs(SpringBootVFS.class);
// 返回 SqlSessionFactory 对象
return factoryBean.getObject();
}
// 创建 SqlSessionTemplate 对象
@Bean("slaveSqlSessionTemplate")
public SqlSessionTemplate slaveSqlSessionTemplate(@Qualifier("slaveSqlSessionFactory") SqlSessionFactory slaveSqlSessionFactory) {
// 创建 SqlSessionTemplate 对象
return new SqlSessionTemplate(slaveSqlSessionFactory);
}
}
2.2、添加数据源配置信息
在【application.yml】中添加master、slave两个数据源的配置信息,如下:
# 配置数据源
spring:
datasource:
# master 数据源信息
master:
driver-class-name: com.mysql.cj.jdbc.Driver # 数据库驱动
url: jdbc:mysql://localhost:3306/sp-demo01?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=UTF-8 # 数据库地址
username: root
password: root
# slave 数据源信息
slave:
driver-class-name: com.mysql.cj.jdbc.Driver # 数据库驱动
url: jdbc:mysql://localhost:3306/sp-demo02?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=UTF-8 # 数据库地址
username: root
password: root
2.3、创建Mapper接口
(1)创建Master的mapper接口
在【com.spring.boot.demo.master.mapper】包下面,创建【EmpMapper】类。
package com.spring.boot.demo.master.mapper;
import com.spring.boot.demo.pojo.EmpBo;
import java.util.List;
public interface EmpMapper {
/**
* 查询所有员工
*/
List<EmpBo> queryAll();
}
(2)创建Slave的mapper接口
在【com.spring.boot.demo.slave.mapper】包下面,创建【DeptMapper】类。
package com.spring.boot.demo.slave.mapper;
import com.spring.boot.demo.pojo.DeptBo;
import org.apache.ibatis.annotations.Param;
public interface DeptMapper {
/**
* 根据 ID 查询部门
* @param deptId
* @return
*/
DeptBo getDeptById(@Param("deptId") Integer deptId);
}
2.4、创建XML映射文件
(1)创建Master的XML映射文件
在【mappers/master】目录下面,新建【EmpMapper.xml】映射文件。
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.spring.boot.demo.master.mapper.EmpMapper">
<select id="queryAll" resultType="com.spring.boot.demo.pojo.EmpBo">
select
emp_id as empId,
emp_name as empName,
age,
dept_id as deptId
from t_emp
</select>
</mapper>
(2)创建Slave的XML映射文件
在【mappers/slave】目录下面,新建【DeptMapper.xml】映射文件。
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.spring.boot.demo.slave.mapper.DeptMapper">
<select id="getDeptById" resultType="com.spring.boot.demo.pojo.DeptBo" parameterType="java.lang.Integer">
select
dept_id as deptId,
dept_name as deptName
from t_dept
where dept_id = #{deptId}
</select>
</mapper>
2.5、编写测试类
package com.spring.boot.demo.controller;
import com.spring.boot.demo.master.mapper.EmpMapper;
import com.spring.boot.demo.pojo.DeptBo;
import com.spring.boot.demo.pojo.EmpBo;
import com.spring.boot.demo.slave.mapper.DeptMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/**
* @author Js
* @version 1.0.0
* @Date: 2023/09/06 20:30:10
* @Description
*/
@RestController
@RequestMapping("/api")
public class TestController {
@Autowired
private EmpMapper empMapper;
@Autowired
private DeptMapper deptMapper;
@GetMapping("/demo")
public String demo() {
// 查询所有员工信息
List<EmpBo> empBoList = empMapper.queryAll();
System.out.println(empBoList);
// 查询每一个员工的部门信息
for (EmpBo empBo : empBoList) {
DeptBo deptBo = deptMapper.getDeptById(empBo.getDeptId());
System.out.println(deptBo);
}
return "测试成功";
}
}
2.6、运行测试
经过上面几个步骤之后,最终的工程目录结果应该是下面这样子的,如下图:

启动工程,浏览器访问【http://localhost:8080/api/demo】,查看控制台输出结果。

到此,SpringBoot结合MyBatis框架实现多数据源配置就成功啦。
三、多数据源配置方式(注解方式)
1. 配置文件,配置多个数据原
server:
port: 17851
spring:
profiles:
active: test-temporary
---
spring:
application:
name: ecpmanage-provider-temporary
profiles: test-temporary
cloud:
nacos:
discovery:
server-addr: ${NACOS:172.30.36.110:18848}
namespace: ${NACOS_NAMESPACE:d7362014-81f9-41c1-82ed-330069ffb40e}
metadata: { "VERSION": 3.6.0 }
group: ${NACOS_REG_GROUP:DEFAULT_GROUP}
config:
server-addr: ${spring.cloud.nacos.discovery.server-addr}
file-extension: yml
shared-configs: application-prod.${spring.cloud.nacos.config.file-extension}
namespace: ${spring.cloud.nacos.discovery.namespace}
group: ${NACOS_CFG_GROUP:DEFAULT_GROUP}
context-path: ${NACOS_CONTEXTPATH:/nacos}
username: ${NACOS_USERNAME:nacos}
password: ${NACOS_PASSWORD:Group@2026}
servlet:
multipart:
max-file-size: 200MB
max-request-size: 200MB
# 数据库配置
datasource:
dynamic:
druid:
initialSize: 5
minIdle: 5
maxActive: 20
maxWait: 60000
filters: stat
primary: mysql
enabled: true
strict: false
datasource:
mysql:
driver-class-name: com.mysql.cj.jdbc.Driver
username: mysql
password: mysql@0607
url: jdbc:mysql://172.30.101.129:2026/ecpmanage?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=GMT%2B8&allowMultiQueries=true&nullCatalogMeansCurrent=true
erp:
driver-class-name: oracle.jdbc.driver.OracleDriver
#driver-class-name: oracle.jdbc.OracleDriver
username: erp_2026
password: erp_2026
url: jdbc:oracle:thin:@//172.30.119.201:1521/ORCL
# --------------------必须配置-----------------------
autoconfigure:
exclude: com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure
mybatis-plus:
mapper-locations: classpath:/mapper/*Mapper.xml
type-enums-package: com.hy.ecpmanage.enums,com.hy.core.enums,com.hy.ecpmanage.*.enums
configuration:
default-enum-type-handler: com.baomidou.mybatisplus.core.handlers.MybatisEnumTypeHandler
2.引入多数据源驱动
<!--多数据源-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
</dependency>
<!--orcl数据驱动-->
<dependency>
<groupId>com.oracle.database.jdbc</groupId>
<artifactId>ojdbc8</artifactId>
</dependency>
3. 启动类上面添加 @EnableDiscoveryClient 注解
@SpringBootApplication
@MapperScan("com.dept.demo.mapper")
@EnableDiscoveryClient
public class DeptDemoApplication {
public static void main(String[] args) {
SpringApplication.run(DeptDemoApplication.class, args);
}
}
4.mapp接口添加注解 @DS
# mapp接口添加注解 @DS("指定使用那个数据库,不指定默认就会使用Mysql")
@Mapper
@DS("erp")//表示使用了orcl数据库
public interface NccRemoteProjectCalculateMapper {
public List<ErpLaborCostsFeeVO> getLaborCostsWages();
public String getItemkey();
}

5.多数据源事物控制
事物的控制,应该都了解在 Spring 中事物使用
@Transactional注解即可,但是仅针对于单个数据源的情况,多数据源下我们可以使用 jta 来控制,不过在 dynamic-datasource 中又推出了@DSTransactional注解来代替 Spring 的 @Transactional 注解
@Slf4j
@SpringBootTest
class DynamicDatasourceDemoApplicationTests {
@Autowired DB1UserDao db1UserDao;
@Autowired DB2UserDao db2UserDao;
@Test
@DSTransactional
void test1() {
UserEntity entity = new UserEntity();
entity.setName("王五");
entity.setAge(16);
int db1 = db1UserDao.insert(entity);
log.info("db1写入个数:{} ", db1);
int db2 = db2UserDao.insert(entity);
log.info("db2写入个数:{} ", db2);
//模拟异常
int a = 1 / 0; }
}

1419

被折叠的 条评论
为什么被折叠?



