Spring Boot 2系列(三十九):Spring Boot 2.x + Mybatis + Druid + Common Mapper 配置多数据源
项目需要连接多个数据库时,在不使用数据库中间件的情况下,就需要配置多个数据源,如主从数据库、新旧数据库(结构不一致)。
手头项目新需求需要连接两个数据库,需要配置两个数据源。项目的基本结构是基于 Spring Boot 2.x + Mybatis + Druid + Common Mapper + PageHelper,所以本篇也是在此基础实现多数据源的配置,留个记录。
数据源
使用了数据库连接池(Druid)来对数据源进行管理。数据源的工作主要是读取数据库配置参数创建数据源,基本参数有 driverClassName,url,username,password等等。
强烈注意:使用 Druid 连接池,Spring Boot 2.X 版本不再支持配置继承,多数据源的话每个数据源的所有配置都需要单独配置,否则配置不会生效。
自定义每个数据源:
- 创建自定义数据源 DataSource 实例,注入数据源配置参数。
- 创建用于生产 sqlSession 的 SqlSessionFactory 实例,需要注入自定义的数据源。
- 创建 SqlSessionTemplate,需要注入自定义的 SqlSessionFactory, 管理 sqlSession。
- 创建自定义的事务管理 DataSourceTransactionManager,需要注入自定义的数据源。
配置实现
- 数据库连接参数和 Mybatis 配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45#=============DataSource One=================
net.sf.log4jdbc.sql.jdbcapi.DriverSpy =
jdbc:log4jdbc:mysql://localhost:3306/sakila?useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&autoReconnect=true&serverTimezone=GMT%2B8 =
panda =
123456 =
master =
com.alibaba.druid.pool.DruidDataSource =
1 =
30 =
1 =
60000 =
select 1 =
1 =
true =
true =
true =
#=============DataSource Two=================
net.sf.log4jdbc.sql.jdbcapi.DriverSpy =
jdbc:log4jdbc:mysql://localhost:3306/sakila_slave?useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&autoReconnect=true&serverTimezone=GMT%2B8 =
panda =
123456 =
slave =
com.alibaba.druid.pool.DruidDataSource =
1 =
30 =
1 =
60000 =
select 1 =
1 =
true =
true =
true =
#============MyBatis配置===================
#mybatis.mapper-locations=classpath:mapper/*.xml
#mybatis.type-aliases-package=com.springboot.template.entity
#mybatis.configuration.map-underscore-to-camel-case=true
#===========通用Mapper=====================
com.springboot.template.mapper.base.BaseMapper =
true =
true =
true =
true = - 两个自定义数据源配置类
DataSourceOneConfig:DataSourceTwoConfig:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97package com.springboot.template.common.datasource;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
import com.springboot.template.mapper.base.BaseMapper;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
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 org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import tk.mybatis.spring.annotation.MapperScan;
import javax.sql.DataSource;
/**
* @name: DataSourceOneConfig
* @desc: 多数据源配置之数据源1
**/
public class DataSourceOneConfig {
/**
* @desc: 数据源 1
* @param: []
* @return: javax.sql.DataSource
**/
public DataSource dataSourceOne() {
//一定要用DruidDataSource类,不然的话druid数据库连接池是不会起作用的
// DruidDataSource dataSourceOne = new DruidDataSource();
DruidDataSource dataSourceOne = DruidDataSourceBuilder.create().build();
return dataSourceOne;
}
/**
* @desc: sqlSession 配置
* @param: []
* @return: org.apache.ibatis.session.Configuration
**/
public org.apache.ibatis.session.Configuration configurationOne() {
org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration();
//开启驼峰映射
configuration.setMapUnderscoreToCamelCase(true);
return configuration;
}
/**
* @desc: SqlSessionFactory 1
* @param: [dataSource]
* @return: org.apache.ibatis.session.SqlSessionFactory
**/
public SqlSessionFactory sqlSessionFactoryOne( DataSource dataSource)throws Exception {
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(dataSource);
//指定mapper xml目录
ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
sqlSessionFactoryBean.setMapperLocations(resolver.getResources("classpath:mapper/*.xml"));
sqlSessionFactoryBean.setTypeAliasesPackage("com.springboot.template.entity");
sqlSessionFactoryBean.setConfiguration(configurationOne());
return sqlSessionFactoryBean.getObject();
}
/**
* @desc: SqlSessionTemplate
* @param: [sqlSessionFactory]
* @return: SqlSessionTemplate
**/
public SqlSessionTemplate sqlSessionTemplateOne( SqlSessionFactory sqlSessionFactory){
return new SqlSessionTemplate(sqlSessionFactory);
}
/**
* @desc: 数据源1的事务管理
* @param: [dataSource]
* @return: org.springframework.jdbc.datasource.DataSourceTransactionManager
**/
public DataSourceTransactionManager dataSourceTransactionManagerOne( DataSource dataSource){
return new DataSourceTransactionManager(dataSource);
}
}配置说明:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92package com.springboot.template.common.datasource;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
import com.springboot.template.mapper.base.BaseMapper;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
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 org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import tk.mybatis.spring.annotation.MapperScan;
import javax.sql.DataSource;
/**
* @name: DataSourceTwoConfig
* @desc: 多数据源配置之数据源2
**/
public class DataSourceTwoConfig {
/**
* @desc: 数据源2
* @param: []
* @return: javax.sql.DataSource
**/
public DataSource dataSourceTwo() {
//一定要用DruidDataSource类,不然的话druid数据库连接池是不会起作用的
// DruidDataSource dataSourceTwo = new DruidDataSource();
DruidDataSource dataSourceTwo = DruidDataSourceBuilder.create().build();
return dataSourceTwo;
}
/**
* @desc: sqlSession 配置
* @param: []
* @return: org.apache.ibatis.session.Configuration
**/
public org.apache.ibatis.session.Configuration configurationTwo() {
org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration();
//开启驼峰映射
configuration.setMapUnderscoreToCamelCase(true);
return configuration;
}
/**
* @desc: SqlSessionFactory 2
* @param: [dataSource]
* @return: org.apache.ibatis.session.SqlSessionFactory
**/
public SqlSessionFactory sqlSessionFactoryTwo( DataSource dataSource)throws Exception {
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(dataSource);
//指定mapper xml目录
ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
sqlSessionFactoryBean.setMapperLocations(resolver.getResources("classpath:mapper/*.xml"));
sqlSessionFactoryBean.setTypeAliasesPackage("com.springboot.template.entity");
sqlSessionFactoryBean.setConfiguration(configurationTwo());
return sqlSessionFactoryBean.getObject();
}
/**
* @desc: SqlSessionTemplate
* @param: [sqlSessionFactory]
* @return: SqlSessionTemplate
**/
public SqlSessionTemplate sqlSessionTemplateTwo( SqlSessionFactory sqlSessionFactory){
return new SqlSessionTemplate(sqlSessionFactory);
}
/**
* @desc: 数据源2的事务管理
* @param: [dataSource]
* @return: org.springframework.jdbc.datasource.DataSourceTransactionManager
**/
public DataSourceTransactionManager dataSourceTransactionManagerTwo( DataSource dataSource){
return new DataSourceTransactionManager(dataSource);
}
}
@Configuration:说明是配置为,注册为 Spring Bean。
@MapperScan:扫描 Mapper 接口,区分不同的数据源。
@Primary:指定主数据源,有且只能有一个主数据源,否则报错。
@ConfigurationProperties:读取 properties 配置文件中的数据库连接参数, 用于设置 DataSourceProperties 的属性。 特别注意:
因此 demo 集成的是 mybatis-spring-boot-starter 包,在默认的单数据源时,可以在 properties 文件配置 mybatis,如下:而多数据源则不支持此方式配置, 每个数据源必须有自己的配置, 包括指定 xxxMapper.xml 文件路径, 定义实体类别名, 开启驼峰规则,否则会报无法绑定 Mapper 接口方法的错误。1
2
3
4#============MyBatis配置===================
classpath:mapper/*.xml =
com.springboot.template.entity =
true = - 两个数据源对应的 Mapper 接口路径
1
2com.springboot.template.mapper.source1.UserMapperOne.java
com.springboot.template.mapper.source2.UserMapperTwo.java - 与两个数据源 Mapper 接口对应的 xxxMapper.xml文件。
1
2src/resources/mapper/UserMapperOne.xml
src/resources/mapper/UserMapperTwo.xml - 多数据源使用
在业务层,根据需要注入多个数据源的 Mapper, 调用 Mapper 接口。 - 配置了两个数据源,若要配置更多数据源,同样的操作。
源码
GitHub -> Spring-Boot-Example/spring-boot-multiple-datasource/
相关参考
Spring Boot 2系列(三十九):Spring Boot 2.x + Mybatis + Druid + Common Mapper 配置多数据源
http://blog.gxitsky.com/2019/02/15/SpringBoot-39-multiple-datasource/