1.背景说明 2.配置多数据源步骤
2.1 项目结构变更
2.2 添加配置类
2.3 修改配置文件数据连接配置信息
2.4 多数据源配置导致@Transactional失效问题
1.背景说明
一般一个项目中只会连接一个数据库.但是随着需求变更,会要求同一个项目中连接多个数据库,本文就讲一下如何在一个项目中对多个数据库进行连接.本文基于springboot+mybatis介绍如何进行多数据源连接(本文演示配置两个数据库,配置多个同理).
2.配置多数据源步骤
2.1 项目结构变更
以连接不同的数据库进行分包,db1表示连接数据库database1,db2表示连接database2.项目结构如下:
2.2添加配置类
/**
* @ClassName: MultiDataSourceConfig
* @Desc: 多数据源配置
* @Author: txm
* @Date: 2022/12/11 9:59
**/
@Configuration
public class MultiDataSourceConfig {
// 创建自定义数据源db1
@Bean(name = "db1")
@ConfigurationProperties(prefix = "spring.datasource.db1")
public DataSource businessDbDataSource() {
return DataSourceBuilder.create().build();
}
// 创建自定义数据源db2
@Bean(name = "db2")
@ConfigurationProperties(prefix = "spring.datasource.db2")
public DataSource newhomeDbDataSource() {
return DataSourceBuilder.create().build();
}
}
Db1Config配置类:
@Configuration
// 此处添加项目自定义mapper包路径,支持数组形式,指定SqlSessionFactory ,演示包路径已做修改
@MapperScan(basePackages = {"com.api.db1.order.mapper",
"com.api.db1.pay.mapper",
"com.api.db1.user.mapper",
"com.api.db1.distribution.mapper",
"com.api.db1.aliyun.mapper" }, sqlSessionFactoryRef = "sqlSessionFactoryDb1")
public class Db1Config {
@Autowired
@Qualifier("db1")
private DataSource dataSourceDb1;
@Bean
public SqlSessionFactory sqlSessionFactoryDb1() throws Exception {
SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
factoryBean.setDataSource(dataSourceDb1);
factoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mapper/db1/**/*.xml"));
// 自定义MyBatis configuration.配置打印和大小写转换
org.apache.ibatis.session.Configuration personalConfiguration = new org.apache.ibatis.session.Configuration();
personalConfiguration.setMapUnderscoreToCamelCase(true);
personalConfiguration.setLogImpl(StdOutImpl.class);
factoryBean.setConfiguration(personalConfiguration);
return factoryBean.getObject();
}
@Bean
public SqlSessionTemplate sqlSessionTemplateDb1() throws Exception {
return new SqlSessionTemplate(sqlSessionFactoryDb1());
}
/**
* @Author: txm
* @Description: 配置事务管理器
* @Param: [dataSource]
* @return: org.springframework.jdbc.datasource.DataSourceTransactionManager
* @Date: 2023/1/31 14:00
**/
@Bean(name="db1TransactionManager")
public DataSourceTransactionManager postgreTransactionManagerGenerate(){
return new DataSourceTransactionManager(dataSourceDb1);
}
}
Db2Config配置类:
@Configuration
// 此处添加项目自定义mapper包路径,支持数组形式,指定SqlSessionFactory ,演示包路径已做修改
@MapperScan(basePackages = {"com.api.db2.activityUser.mapper",
"com.api.db2.vote.mapper"}, sqlSessionFactoryRef = "sqlSessionFactoryDb2")
public class Db2Config {
@Autowired
@Qualifier("db2")
private DataSource dataSourceDb2;
@Bean
public SqlSessionFactory sqlSessionFactoryDb2() throws Exception {
SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
factoryBean.setDataSource(dataSourceDb2);
factoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mapper/db2/**/*.xml"));
// 自定义MyBatis configuration.配置打印和大小写转换
org.apache.ibatis.session.Configuration personalConfiguration = new org.apache.ibatis.session.Configuration();
personalConfiguration.setMapUnderscoreToCamelCase(true);
personalConfiguration.setLogImpl(StdOutImpl.class);
factoryBean.setConfiguration(personalConfiguration);
return factoryBean.getObject();
}
@Bean
public SqlSessionTemplate sqlSessionTemplateDb2() throws Exception {
return new SqlSessionTemplate(sqlSessionFactoryDb2());
}
/**
* @Author: txm
* @Description: 配置事务管理器
* @Param: [dataSource]
* @return: org.springframework.jdbc.datasource.DataSourceTransactionManager
* @Date: 2023/1/31 14:00
**/
@Bean(name="db2TransactionManager")
public DataSourceTransactionManager postgreTransactionManagerGenerate(){
return new DataSourceTransactionManager(dataSourceDb2);
}
}
说明
自定义配置类Db1Config
、Db2Config
中指定 @MapperScan
之后可以将启动类上面的@MapperScan
注解进行注释,@MapperScan
的作用就是扫描mapper所在的包路径:
// modify by txm 2022/12/12 多数据源改造,包扫描添加到自定义数据源配置类Db1Config、Db2Config中
//@MapperScan("com.**.mapper")
@SpringBootApplication
public class H5Application {
public static void main(String[] args) {
SpringApplication.run(H5Application.class, args);
}
}
配置类中指定mapper配置文件所在路径,否则会提示:org.apache.ibatis.binding.BindingException: Invalid bound statement (not found)
,添加内容如下::
factoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mapper/db2/**/*.xml"));
对应的配置文件是(可以进行注释):
mybatis:
# 配置数据库映射文件 **表示是任意多级目录,适配dao/goods
mapper-locations: classpath:/mapper/**/**/*.xml
配置mybatis的日志打印与大小写转换:
// 自定义MyBatis configuration.配置打印和大小写转换
org.apache.ibatis.session.Configuration personalConfiguration = new org.apache.ibatis.session.Configuration();
personalConfiguration.setMapUnderscoreToCamelCase(true);
personalConfiguration.setLogImpl(StdOutImpl.class);
factoryBean.setConfiguration(personalConfiguration);
添加之后配置文件中可以将以下内容进行注释:
mybatis:
# 配置数据库映射文件 **表示是任意多级目录,适配dao/goods
mapper-locations: classpath:/mapper/**/**/*.xml
#spring boot集成mybatis的方式打印sql
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
#spring boot记成mybatis将数据库字段字段转换华成驼峰形式
map-underscore-to-camel-case: true
2.3 修改配置文件数据连接配置信息
spring:
#数据库信息设置
datasource:
db1: # database1服务器地址
jdbc-url: jdbc:mysql://xxx.xxx.xx.xx:3308/database1?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf8&useSSL=false&allowPublicKeyRetrieval=true&allowMultiQueries=true
username: ****
password: ****
driver-class-name: com.mysql.cj.jdbc.Driver
db2: # database2服务器地址
jdbc-url: jdbc:mysql://xxx.xxx.xx.xx:3308/database2?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf8&useSSL=false&allowPublicKeyRetrieval=true&allowMultiQueries=true
username: ****
password: ****
driver-class-name: com.mysql.cj.jdbc.Driver
# 配置数据库连接池
type: com.zaxxer.hikari.HikariDataSource
hikari:
minimum-idle: 5 # 最小空闲连接数量
idle-timeout: 180000 # 单位毫秒,此处设置3分钟,空闲连接存活最大时间,默认600000(10分钟)
maximum-pool-size: 10 # 连接池最大连接数,默认是10
auto-commit: true # 此属性控制从池返回的连接的默认自动提交行为,默认值:true
pool-name: MyHikariCP # 连接池名称
max-lifetime: 1800000 # 此属性控制池中连接的最长生命周期,值0表示无限生命周期,默认1800000即30分钟
connection-timeout: 30000 # 数据库连接超时时间,默认30秒,即30000
注意:要将url替换成jdbc-url,否则会提示以下内容:
java.lang.IllegalArgumentException: jdbcUrl is required with driverClassName.
关于数据库连接类型可以选用springboot默认支持的Hikari
,性能会更好!如果对Hikari
无配置要求,可以不用添加Hikari相关的配置信息.演示内容中配置了db2的Hikari
信息.
2.4 多数据源配置导致@Transactional失效问题
多数据源改造之后会导致@Transactional失效,处理方案如下:Db1Config.java
、Db2Config.java
中需要进行注册对应的事务管理器,已经在刚开始的案例中进行了补充。使用的时候需要根据不同的数据源替换掉默认的事务管理器。
以抽奖接口为例说明:
原接口:
@Override
@Transactional(rollbackFor = Exception.class)
public synchronized DrawVo luckDraw(LuckDrawDto luckDrawDto) {
// 忽略业务处理逻辑
}
多数据源事务管理改造之后:
@Override
@Transactional(transactionManager = "db2TransactionManager",rollbackFor = Exception.class)
public synchronized DrawVo luckDraw(LuckDrawDto luckDrawDto) {
// 忽略业务处理逻辑
}
以上是关于springboot中配置多数据源的实战记录,希望对有同样需求的同学有所帮助,感觉有所收获欢迎点赞或是留言!