SpringBoot框架实现多数据源操作,首先需要搭建Mybatis的运行环境。
由于是多数据源,也就是要有多个数据库,所以,我们创建两个测试数据库,分别是:【sp-demo01】和【sp-demo02】,如下图所示:
具体SQL代码:
-- 创建数据库
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');
-- 创建数据库
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');
MyBatis框架中,提供了一个**【@MapperScan】注解,该注解作用是指定mapper接口所在的路径,并且这个注解中,也可以指定使用哪个【SqlSessionFactory】对象,只需要通过该注解的【sqlSessionFactoryRef】**属性即可实现。
这里的SqlSessionFactory就相当于是一个数据库,如果我们要配置多数据源,那就相当于是要在工程里面创建多个SqlSessionFactory对象,然后再使用的时候指定具体的SqlSessionFactory对象即可。
配置数据源,需要创建三个对象,分别是下面三个:
知道了这个知识,那就可以进行多数据源配置啦。
这里,我们就创建两个数据源作为测试案例,两个数据源分别叫做【MasterDataSource】和【SlaveDataSource】。
在工程中,创建一个【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);
}
}
在工程中,创建一个【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);
}
}
在【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
在【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();
}
在【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);
}
在【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>
在【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>
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 "测试成功";
}
}
经过上面几个步骤之后,最终的工程目录结果应该是下面这样子的,如下图:
启动工程,浏览器访问【http://localhost:8080/api/demo】,查看控制台输出结果。
到此,SpringBoot结合MyBatis框架实现多数据源配置就成功啦。