实战项目中经常遇见需要配置多个数据源的情况,这篇文章主要介绍一下如何集成Mybatis来实现多数据源配置。
1. 先导入需要的jar包
需要注意的是MySQL、SQL Server不同数据库需要的驱动jar包不一样,自主选择引入
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>2.0.32</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.2</version>
</dependency>
<dependency>
<groupId>com.microsoft.sqlserver</groupId>
<artifactId>mssql-jdbc</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.23</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
</dependencies>
2. application.yml配置文件
注意:Spring Boot 2.X 版本不再支持配置继承,多数据源的话每个数据源的所有配置都需要单独配置,否则配置不会生效。
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
druid:
rbk:
driverClassName: com.microsoft.sqlserver.jdbc.SQLServerDriver
# driver-class-name=com.mysql.jdbc.Driver
# jdbc-url: jdbc:mysql://localhost:3306/database01?useUnicode=true&characterEncoding=utf8&autoReconnect=true&failOverReadOnly=false
url: jdbc:sqlserver://127.0.0.1:1433;DatabaseName=rbk
username: root
password: root123456@
pbi:
driverClassName: com.microsoft.sqlserver.jdbc.SQLServerDriver
# driver-class-name=com.mysql.jdbc.Driver
# jdbc-url: #jdbc-url: jdbc:mysql://localhost:3306/database02?useUnicode=true&characterEncoding=utf8&autoReconnect=true&failOverReadOnly=false
url: jdbc:sqlserver://127.0.0.1:1433;DatabaseName=pbi
username: root
password: root123456@
# 初始连接数
initial-size: 5
# 最小连接数
min-idle: 15
# 最大连接数
max-active: 30
# 超时时间(以秒数为单位)
remove-abandoned-timeout: 180
# 获取连接超时时间
max-wait: 3000
# 连接有效性检测时间
time-between-eviction-runs-millis: 60000
# 连接在池中最小生存的时间
min-evictable-idle-time-millis: 300000
# 连接在池中最大生存的时间
max-evictable-idle-time-millis: 900000
# 指明连接是否被空闲连接回收器(如果有)进行检验.如果检测失败,则连接将被从池中去除
test-while-idle: true
# 指明是否在从池中取出连接前进行检验,如果检验失败, 则从池中去除连接并尝试取出另一个
test-on-borrow: true
# 是否在归还到池中前进行检验
test-on-return: false
# 检测连接是否有效
validation-query: select 1
servlet:
multipart:
enabled: true #默认支持文件上传
max-file-size: 10MB #最大支持文件大小
max-request-size: 10MB #最大支持请求大小,不可省略
# mybatis 配置
mybatis:
type-aliases-package: com.study.framework.entity
mapper-locations: classpath*:mappers/**/*.xml
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
map-underscore-to-camel-case: true
3. 数据库配置类
3.1 默认库配置类
package com.study.framework.config;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
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 org.springframework.jdbc.datasource.DataSourceTransactionManager;
import javax.sql.DataSource;
/**
* @description rbk数据源配置类
* //basePackages 自己mapper包路径
*/
@Configuration
@MapperScan(basePackages = {"com.study.framework.mapper.rbkmapper"}, sqlSessionFactoryRef = "rbkSqlSessionFactory")
public class rbkDataSourceConfiguration {
@Primary
@Bean(name = "rbkDataSourceProperties")
@ConfigurationProperties(prefix = "spring.datasource.druid.rbk")
public DataSourceProperties rbkDataSourceProperties() {
return new DataSourceProperties();
}
@Primary
@Bean(name = "rbkDataSource")
public DataSource storyDataSource(@Qualifier("rbkDataSourceProperties") DataSourceProperties rbkDataSourceProperties) {
return rbkDataSourceProperties.initializeDataSourceBuilder().build();
}
@Primary
@Bean("rbkSqlSessionFactory")
public SqlSessionFactory rbkSqlSessionFactory(@Qualifier("rbkDataSource") DataSource rbkDataSource) throws Exception {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(rbkDataSource);
bean.setMapperLocations(
// 设置mybatis的xml所在位置
new PathMatchingResourcePatternResolver().getResources("classpath*:mappers/rbkmapper/*.xml"));
bean.setTypeAliasesPackage("com.study.framework.entity"); //自己entity包路径
return bean.getObject();
}
@Primary
@Bean(name = "rbkTransactionManager")
public DataSourceTransactionManager rbkTransactionManager(@Qualifier("rbkDataSource") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
@Primary
@Bean(name = "rbkSqlSessionTemplate")
public SqlSessionTemplate rbkSqlSessionTemplate(@Qualifier("rbkSqlSessionFactory") SqlSessionFactory sqlSessionFactory) {
return new SqlSessionTemplate(sqlSessionFactory);
}
}
3.2 添加第二个数据源配置类
package com.study.framework.config;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
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 org.springframework.jdbc.datasource.DataSourceTransactionManager;
import javax.sql.DataSource;
/**
* @description pbi数据源配置类
*/
@Configuration
@MapperScan(basePackages = {"com.study.framework.mapper.pbimapper"}, sqlSessionFactoryRef = "pbiSqlSessionFactory")
public class PbiDataSourceConfiguration {
@Bean(name = "pbiDataSourceProperties")
@ConfigurationProperties(prefix = "spring.datasource.druid.pbi")
public DataSourceProperties pbiDataSourceProperties() {
return new DataSourceProperties();
}
@Bean(name = "pbiDataSource")
public DataSource storyDataSource(@Qualifier("pbiDataSourceProperties") DataSourceProperties pbiDataSourceProperties) {
return pbiDataSourceProperties.initializeDataSourceBuilder().build();
}
@Bean("pbiSqlSessionFactory")
public SqlSessionFactory pbiSqlSessionFactory(@Qualifier("pbiDataSource") DataSource pbiDataSource) throws Exception {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(pbiDataSource);
bean.setMapperLocations(
// 设置mybatis的xml所在位置
new PathMatchingResourcePatternResolver().getResources("classpath*:mappers/pbimapper/*.xml"));
bean.setTypeAliasesPackage("com.study.framework.entity"); //自己的entity包路径
return bean.getObject();
}
@Bean(name = "pbiTransactionManager")
public DataSourceTransactionManager pbiTransactionManager(@Qualifier("pbiDataSource") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
@Bean(name = "pbiSqlSessionTemplate")
public SqlSessionTemplate pbiSqlSessionTemplate(@Qualifier("pbiSqlSessionFactory") SqlSessionFactory sqlSessionFactory) {
return new SqlSessionTemplate(sqlSessionFactory);
}
}
解释一下几个注解:
@Primary:可以理解成它标识了默认数据源
@ConfigurationProperties(prefix = ““):读取YML配置文件中的参数映射成一个对象,其中prefix属性表示参数的前缀
@Qualifier(“pbiDataSource”):表示查找Spring容器中名称=pbiDataSource的对象
4. SpringBoot启动类
注意:
① 不需要使用自动配置,那么需要取消加载对应的自动配置类。在启动类关闭 Spring Boot 对数据源的自动化配置;
② 因为数据源配置类中已经使用了@MapperScan注解扫描了指定包,这时SpringBoot启动类中也不需要添加@MapperScan注解了,否则就会重复扫描,抛出警告:
WARN o.m.s.mapper.ClassPathMapperScanner - Skipping MapperFactoryBean with name 'DemoXxxxMapper' and 'com.study.framework.mapper.pbimapper.DemoXxxxMapper' mapperInterface. Bean already defined with the same name!
由我们手动进行多数据源的配置:
package com.study.framework;
import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure;
import org.mybatis.spring.annotation.MapperScan;
import org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;
/**
* @author
*/
@SpringBootApplication(exclude= {DataSourceAutoConfiguration.class, MybatisAutoConfiguration.class, DruidDataSourceAutoConfigure.class})
@ComponentScan("com.study.framework.*")
//@MapperScan(value = {"com.study.framework.rbkmapper", "com.study.framework.pbimapper"})
public class FrameworkApplication {
public static void main(String[] args) {
SpringApplication.run(FrameworkApplication.class, args);
}
}
到这一步多数据源基本就已经配置完成了,接下来就是调试阶段,自己在不同数据库下创建一张表,然后编写Mapper和xml就可以测试了。下面是我Demo项目的整体目录:

5. Demo测试一下
5.1 Dao层
对应的数据源下编写一个Mapper接口和对应的xxMapper.xml文件
@Repository
public interface UserInfoMapper {
UserInfoPO selectUserInfoByName(@Param("name") String name);
}
@Repository
public interface StudentInfoMapper {
StudentInfoPO selectStudentInfoByName(@Param("name") String name);
}
对应的UserInfoMapper.xml 和 StudentInfoMapper.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.study.framework.mapper.rbkmapper.UserInfoMapper">
<resultMap id="BaseResultMap" type="com.study.framework.entity.UserInfoPO">
<id column="id" property="id" jdbcType="INTEGER"/>
<result column="name" property="name" jdbcType="VARCHAR"/>
<result column="work" property="workcode" jdbcType="VARCHAR"/>
<result column="number" property="number" jdbcType="INTEGER"/>
<result column="status" property="status" jdbcType="INTEGER"/>
</resultMap>
<select id="selectUserInfoByName" resultMap="BaseResultMap">
select id, name, work, number, status
from user_info
where name = #{name}
</select>
</mapper>
```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.study.framework.mapper.rbkmapper.StudentInfoMapper">
<resultMap id="BaseResultMap" type="com.study.framework.entity.StudentInfoPO">
<id column="id" property="id" jdbcType="INTEGER"/>
<result column="name" property="name" jdbcType="VARCHAR"/>
<result column="student_code" property="workcode" jdbcType="VARCHAR"/>
<result column="age" property="number" jdbcType="INTEGER"/>
<result column="status" property="status" jdbcType="INTEGER"/>
</resultMap>
<select id="selectStudentInfoByName" resultMap="BaseResultMap">
select id, name, student_code, age, status
from student_info
where name = #{name}
</select>
</mapper>
5.2 Service层和Impl实现类
public interface InformationService {
UserInfoPO getUserInfo(String name);
StudentInfoPO getStudentInfo(String name);
}
/**
* @author
*/
@Slf4j
@Service
public class InformationServiceImpl implements InformationService {
@Autowired
private UserInfoMapper userInfoMapper;
@Autowired
private StudentInfoMapper studentInfoMapper;
@Override
public UserInfoPO getUserInfo(String userName) {
return userInfoMapper.selectUserInfoByName(userName);
}
@Override
public StudentInfoPO getStudentInfo(String studentName) {
return userInfoMapper.selectStudentInfoByName(studentName);
}
}
5.3 Controller层
/**
* @author
* @description
* @date 2024-07-15 20:14
*/
@RestController
@RequestMapping("/people")
public class PeopleController {
@Autowired
private InformationService informationService ;
@RequestMapping(value = "/user/info", method = RequestMethod.GET)
public RespResult<?> getUserInfo(@RequestParam("name") String name) {
UserInfoPO userinfo= informationService.getUserInfo(name);
return RespResult.successWithData(userinfo);
}
@RequestMapping(value = "/student/info", method = RequestMethod.GET)
public RespResult<?> getUserInfo(@RequestParam("name") String name) {
StudentInfoPO studentInfo= informationService.getStudentInfo(userName);
return RespResult.successWithData(userinfo);
}
}
5.4 Postman请求结果
//http://localhost:8008/framework/people/user/info?name=测评
{
"code": 0,
"message": "操作成功",
"data": {
"id": 2,
"name": "测评",
"work": "user001",
"number": 10,
"status": 1
},
"pageBase": null
}
//http://localhost:8008/framework/people/student/info?name=测评
{
"code": 0,
"message": "操作成功",
"data": {
"id": 2,
"name": "测评",
"student_code": "stu001",
"age": 10,
"status": 1
},
"pageBase": null
}
原文链接: https://onlyou.blog.csdn.net//article/details/140465591