springboot2多数据源的配置及使用
参考
https://blog.csdn.net/tuesdayma/article/details/81081666
https://www.cnblogs.com/ziyue7575/p/e97bcad8ed323602251ca3bd2b1a4457.html
https://blog.csdn.net/weixin_44605704/article/details/97746557
1 说明
多数据源有两种配置方式,一种为通过包名区分不同数据源,一种为通过注解获取动态数据源。
2 分包方式
配置数据源
在application.yml配置文件中配置数据源连接信息。不同数据源配置好别名,如下图,“first”和“second”为两个数据源别名。
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
druid:
first:
url: jdbc:mysql://localhost:3306/more_data_source?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf8&useSSL=false&allowPublicKeyRetrieval=true
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver
second:
url: jdbc:mysql://localhost:3306/moreDataSource?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf8&useSSL=false&allowPublicKeyRetrieval=true
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver
数据库的其它配置可添加到对应数据库别名下,如下图:
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
druid:
first:
url: jdbc:mysql://localhost:3306/more_data_source?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf8&useSSL=false&allowPublicKeyRetrieval=true
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver
# 数据库的其它配置可以在这里追加设置
initial-size: 10
max-active: 100
max-pool-prepared-statement-per-connection-size: 20
max-wait: 60000
min-evictable-idle-time-millis: 300000
min-idle: 10
pool-prepared-statements: true
# 其它配置内容这里就先省略了。。。
mybatis-plus配置
去掉“mapper-locations”配置。
mybatis-plus:
# 启动时是否检查MyBatis XML文件是否存在
check-config-location: true
# MyBatis原生配置
configuration:
# 字段名称下划线转驼峰命名
map-underscore-to-camel-case: true
global-config:
db-config:
# 全局默认主键类型
id-type: id_worker
# 逻辑已删除值(默认为 1)
logic-delete-value: 1
# 逻辑未删除值(默认为 0)
logic-not-delete-value: 0
# mapper xml映射路径
# mapper-locations: classpath*:mapper/**/*Mapper.xml
Application类
去掉“@MapperScan”注解,分包方式会根据不同包配置不同的mapper扫描路径,配置方式见下节数据源配置类。
@SpringBootApplication
//@MapperScan({"com.test.springbootplus.**.mapper"})
public class MoreDataSourceApplication {
public static void main(String[] args) {
SpringApplication.run(MoreDataSourceApplication .class, args);
}
}
数据源配置类
注意不同数据源中“MapperScan”和“MapperLocations”配置不同,且需确保配置的地址正确。
第一个数据源配置类:
@Configuration
// 配置mybatis的接口类放的地方
@MapperScan(basePackages = "com.test.springbootplus.dataSource1.*.domain.mapper", sqlSessionFactoryRef = "test1SqlSessionFactory")
public class DataSourceConfig1 {
@Bean(name = "test1DataSource")
// 表示这个数据源是默认数据源
@Primary
// 读取application.yml中的配置参数映射成为一个对象
@ConfigurationProperties(prefix = "spring.datasource.druid.first")
public DruidDataSource getDateSource1() {
return new DruidDataSource();
}
@Bean(name = "test1SqlSessionFactory")
@Primary
// @Qualifier表示查找Spring容器中名字为test1DataSource的对象
public SqlSessionFactory test1SqlSessionFactory(@Qualifier("test1DataSource") DataSource datasource)
throws Exception {
MybatisSqlSessionFactoryBean sqlSessionFactoryBean = new MybatisSqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(datasource);
// 这里注意地址的准确性!!!
sqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath*:mapper/dataSource1/test/*Mapper.xml"));
return sqlSessionFactoryBean.getObject();
}
//事务管理器
@Bean(name = "test1TransactionManager")
@Primary
public DataSourceTransactionManager slaveTransactionManager() {
return new DataSourceTransactionManager(getDateSource1());
}
@Bean("test1SqlSessionTemplate")
@Primary
public SqlSessionTemplate test1sqlsessiontemplate(
@Qualifier("test1SqlSessionFactory") SqlSessionFactory sessionfactory) {
return new SqlSessionTemplate(sessionfactory);
}
}
同上配置第二个数据源配置类:
@Configuration
@MapperScan(basePackages = "com.test.springbootplus.dataSource2.*.domain.mapper", sqlSessionFactoryRef = "test2SqlSessionFactory")
public class DataSourceConfig2 {
@Bean(name = "test2DataSource")
@ConfigurationProperties(prefix = "spring.datasource.druid.second")
public DruidDataSource getDateSource2() {
return new DruidDataSource();
}
@Bean(name = "test2SqlSessionFactory")
public SqlSessionFactory test2SqlSessionFactory(@Qualifier("test2DataSource") DataSource datasource)
throws Exception {
MybatisSqlSessionFactoryBean sqlSessionFactoryBean = new MybatisSqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(datasource);
sqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath*:mapper/dataSource2/test/*Mapper.xml"));
return sqlSessionFactoryBean.getObject();
}
//事务管理器
@Bean(name = "test2TransactionManager")
public DataSourceTransactionManager slaveTransactionManager() {
return new DataSourceTransactionManager(getDateSource2());
}
@Bean("test2SqlSessionTemplate")
public SqlSessionTemplate test2sqlsessiontemplate(
@Qualifier("test2SqlSessionFactory") SqlSessionFactory sessionfactory) {
return new SqlSessionTemplate(sessionfactory);
}
}
报错及解决
- org.apache.ibatis.binding.BindingException: Invalid bound statement (not found)
报错原因:
- 可能是mapper的xml中,namespace与项目的路径不一致导致的
- 数据源配置类中没有使用MybatisSqlSessionFactoryBean,用的是SqlSessionFactoryBean
@Bean(name = "test1SqlSessionFactory")
@Primary
public SqlSessionFactory firstSqlSessionFactory(@Qualifier("firstDS") DataSource dataSource) throws Exception {
// 这里用的是SqlSessionFactoryBean
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(dataSource);
bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath*:mapper/dataSource1/test/*Mapper.xml"));
return bean.getObject();
}
改为
@Bean(name = "test1SqlSessionFactory")
@Primary
public SqlSessionFactory test1SqlSessionFactory(@Qualifier("test1DataSource") DataSource datasource) throws Exception {
// 改用MybatisSqlSessionFactoryBean
MybatisSqlSessionFactoryBean sqlSessionFactoryBean = new MybatisSqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(datasource);
sqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath*:mapper/dataSource1/test/*Mapper.xml"));
return sqlSessionFactoryBean.getObject();
}
- jdbcUrl is required with driverClassName
报错原因:此时可能使用的是springboot默认数据源Hikari,但是Hikari没有url属性,但是有一个jdbcUrl属性,在这种情况下,必须重写配置名“spring.datasource.secondary.url”为“spring.datasource.secondary.jdbc-url”。
如果并不想用默认的Hikari数据源,使用的为Druid,查看数据源配置类中DataSource的获取方式是否如下:
@Bean(name = "test2DataSource")
@ConfigurationProperties(prefix = "spring.datasource.druid.second")
public DataSource getDateSource2() {
return DataSourceBuilder.create().build();
}
修改为:
@Bean(name = "test2DataSource")
@ConfigurationProperties(prefix = "spring.datasource.druid.second")
public DruidDataSource getDateSource2() {
return new DruidDataSource();
}
3 注解方式
使用dynamic进行动态数据源的配置,官方文档:https://mybatis.plus/guide/dynamic-datasource.html#%E6%96%87%E6%A1%A3-documentation。
配置依赖
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
<version>2.2.0</version>
</dependency>
配置数据源
spring:
datasource:
# 可以先在这里配置好通用的配置,比如
druid:
initial-size: 10
max-active: 100
max-pool-prepared-statement-per-connection-size: 20
max-wait: 60000
min-evictable-idle-time-millis: 300000
min-idle: 10
pool-prepared-statements: true
time-between-eviction-runs-millis: 60000
validation-query: SELECT 1
validation-query-timeout: 60000
# 这里就先省略其它更多的配置了
type: com.alibaba.druid.pool.DruidDataSource
#dynamic开始多数据源配置
dynamic:
primary: dataSource1 #设置默认的数据源或者数据源组,默认值即为master
strict: false #设置严格模式,默认false不启动. 启动后在未匹配到指定数据源时候会抛出异常,不启动则使用默认数据源.
datasource:
dataSource1:
url: jdbc:mysql://localhost:3306/more_data_source?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf8&useSSL=false&allowPublicKeyRetrieval=true
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver
dataSource2:
url: jdbc:mysql://ocalhost:3306/moreDataSource?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf8&useSSL=false&allowPublicKeyRetrieval=true
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver
Application类
@SpringBootApplication(exclude = DruidDataSourceAutoConfigure.class)
@MapperScan({"com.test.springbootplus.**.mapper"})
public class LasaBenefitPeopleApplication {
public static void main(String[] args) {
SpringApplication.run(LasaBenefitPeopleApplication.class, args);
}
}
使用
使用@DS切换数据源。@DS可以注解在方法上和类上,同时存在方法注解优先于类上注解。
注解 | 结果 |
---|---|
没有@DS | 默认数据源 |
@DS(“dsName”) | dsName可以为组名也可以为具体某个库的名称 |