所谓的多数据源,简而言之就是:在一个项目中,有多个jdbc连接。

那么我们在在实际项目中,应该怎么样搭建多数据源并区分数据源呢?
举个例子 : 我们这个项目需要访问Test和Test1两个不同的数据库,我们可以采用分包结构,设置读取不同的数据源前缀,选择连接不同数据源。

分包结构
cn.itcats.test--- 访问Test数据库
        dao
        service
cn.itcats.test1--- 访问Test1数据库
        dao
        service

首先在application.properties中引入多数据源配置:
spring.datasource.test.driverClassName = com.mysql.jdbc.Driver
spring.datasource.test.url =
jdbc:mysql://localhost:3306/Test?useUnicode=true&characterEncoding=utf-8
spring.datasource.test.username = root spring.datasource.test.password = root
spring.datasource.test1.driverClassName = com.mysql.jdbc.Driver
spring.datasource.test1.url =
jdbc:mysql://localhost:3306/Test1?useUnicode=true&characterEncoding=utf-8
spring.datasource.test1.username = root spring.datasource.test1.password = root
 

创建cn.itcats.datasource包,新建类DataSource1Config
package cn.itcats.datasource; import javax.sql.DataSource; 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.DataSourceBuilder; 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.jdbc.datasource.DataSourceTransactionManager;
@Configuration //
注册到springboot容器中,相当于@Beans,它和@Bean配合使用,相当于@Bean的类由springioc管理,@Bean只能用在方法上
//@MapperScan代表该数据源类只扫描cn.itcats.mapper.test1下的mapper @MapperScan(basePackages
= "cn.itcats.mapper.test1", sqlSessionFactoryRef = "testSqlSessionFactory")
public class DataSource2Config { @Bean(name = "test1DataSource")
//识别数据源的前缀,注意此处设置不同的前缀 @ConfigurationProperties(prefix =
"spring.datasource.test1") public DataSource testDataSource() { return
DataSourceBuilder.create().build(); } @Bean(name = "test1SqlSessionFactory")
public SqlSessionFactory testSqlSessionFactory(@Qualifier("test1DataSource")
DataSource dataSource) throws Exception { SqlSessionFactoryBean bean = new
SqlSessionFactoryBean(); bean.setDataSource(dataSource);
//若使用mybatis写配置文件,则需要配置 // bean.setMapperLocations( // new
PathMatchingResourcePatternResolver().getResources("classpath:mybatis/mapper/test/*.xml"));
return bean.getObject(); } @Bean(name = "test1TransactionManager") public
DataSourceTransactionManager
testTransactionManager(@Qualifier("test1DataSource") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource); } @Bean(name =
"test1SqlSessionTemplate") public SqlSessionTemplate testSqlSessionTemplate(
@Qualifier("test1SqlSessionFactory") SqlSessionFactory sqlSessionFactory)
throws Exception { return new SqlSessionTemplate(sqlSessionFactory); } }
 

 

新建类DataSource2Config
package cn.itcats.datasource; import javax.sql.DataSource; 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.DataSourceBuilder; 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.jdbc.datasource.DataSourceTransactionManager;
@Configuration //
注册到springboot容器中,相当于@Beans,它和@Bean配合使用,相当于@Bean的类由springioc管理,@Bean只能用在方法上
//@MapperScan代表该数据源类只扫描cn.itcats.mapper.test1下的mapper @MapperScan(basePackages
= "cn.itcats.mapper.test1", sqlSessionFactoryRef = "testSqlSessionFactory")
public class DataSource2Config { @Bean(name = "test1DataSource")
//识别数据源的前缀,注意此处设置不同的前缀 @ConfigurationProperties(prefix =
"spring.datasource.test1") public DataSource testDataSource() { return
DataSourceBuilder.create().build(); } @Bean(name = "test1SqlSessionFactory")
public SqlSessionFactory testSqlSessionFactory(@Qualifier("test1DataSource")
DataSource dataSource) throws Exception { SqlSessionFactoryBean bean = new
SqlSessionFactoryBean(); bean.setDataSource(dataSource);
//若使用mybatis写配置文件,则需要配置 // bean.setMapperLocations( // new
PathMatchingResourcePatternResolver().getResources("classpath:mybatis/mapper/test/*.xml"));
return bean.getObject(); } @Bean(name = "test1TransactionManager") public
DataSourceTransactionManager
testTransactionManager(@Qualifier("test1DataSource") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource); } @Bean(name =
"test1SqlSessionTemplate") public SqlSessionTemplate testSqlSessionTemplate(
@Qualifier("test1SqlSessionFactory") SqlSessionFactory sqlSessionFactory)
throws Exception { return new SqlSessionTemplate(sqlSessionFactory); } }
 

新建 创建分包Mapper

cn.itcats.mapper.test.UserMapperTest

cn.itcats.mapper.test1.UserMapperTest1
public interface UserMapperTest { @Insert("insert into users
values(null,#{name},#{age});") public int addUser(@Param("name") String name,
@Param("age") Integer age); } public interface UserMapperTest { @Insert("insert
into users values(null,#{name},#{age});") public int addUser(@Param("name")
String name, @Param("age") Integer age); }
 

常见错误:

No qualifying bean of type [javax.sql.DataSource] is defined: expected single
matching bean but found 2: testDataSource,test1DataSource

多数据源时,需要配置@Primary

 

 

SpringBoot分布式事物管理

1.pom.xml中引用jta-atomikos
<dependency> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jta-atomikos</artifactId> </dependency>
2.新增配置文件信息
# Mysql 1 mysql.datasource.test1.url =
jdbc:mysql://localhost:3306/test01?useUnicode=true&characterEncoding=utf-8
mysql.datasource.test1.username = root mysql.datasource.test1.password = root
mysql.datasource.test1.minPoolSize = 3 mysql.datasource.test1.maxPoolSize = 25
mysql.datasource.test1.maxLifetime = 20000
mysql.datasource.test1.borrowConnectionTimeout = 30
mysql.datasource.test1.loginTimeout = 30
mysql.datasource.test1.maintenanceInterval = 60
mysql.datasource.test1.maxIdleTime = 60 mysql.datasource.test1.testQuery =
select 1 # Mysql 2 mysql.datasource.test2.url
=jdbc:mysql://localhost:3306/test02?useUnicode=true&characterEncoding=utf-8
mysql.datasource.test2.username =root mysql.datasource.test2.password =root
mysql.datasource.test2.minPoolSize = 3 mysql.datasource.test2.maxPoolSize = 25
mysql.datasource.test2.maxLifetime = 20000
mysql.datasource.test2.borrowConnectionTimeout = 30
mysql.datasource.test2.loginTimeout = 30
mysql.datasource.test2.maintenanceInterval = 60
mysql.datasource.test2.maxIdleTime = 60 mysql.datasource.test2.testQuery =
select 1
3.读取配置文件信息

DBConfig1
@ConfigurationProperties(prefix = "mysql.datasource.test1") public class
DBConfig1 { private String url; private String username; private String
password; private int minPoolSize; private int maxPoolSize; private int
maxLifetime; private int borrowConnectionTimeout; private int loginTimeout;
private int maintenanceInterval; private int maxIdleTime; private String
testQuery; //getter and setter }
DBConfig2
@ConfigurationProperties(prefix = "mysql.datasource.test2") public class
DBConfig2 { private String url; private String username; private String
password; private int minPoolSize; private int maxPoolSize; private int
maxLifetime; private int borrowConnectionTimeout; private int loginTimeout;
private int maintenanceInterval; private int maxIdleTime; private String
testQuery; //getter and setter }
 

创建多数据源
@Configuration // basePackages 最好分开配置 如果放在同一个文件夹可能会报错 @MapperScan(basePackages
= "cn.itcats.test1", sqlSessionTemplateRef = "testSqlSessionTemplate") public
class TestMyBatisConfig1 { // 配置数据源 @Primary @Bean(name = "testDataSource")
public DataSource testDataSource(DBConfig1 testConfig) throws SQLException {
MysqlXADataSource mysqlXaDataSource = new MysqlXADataSource();
mysqlXaDataSource.setUrl(testConfig.getUrl());
mysqlXaDataSource.setPinGlobalTxToPhysicalConnection(true);
mysqlXaDataSource.setPassword(testConfig.getPassword());
mysqlXaDataSource.setUser(testConfig.getUsername());
mysqlXaDataSource.setPinGlobalTxToPhysicalConnection(true);
AtomikosDataSourceBean xaDataSource = new AtomikosDataSourceBean();
xaDataSource.setXaDataSource(mysqlXaDataSource);
xaDataSource.setUniqueResourceName("testDataSource");
xaDataSource.setMinPoolSize(testConfig.getMinPoolSize());
xaDataSource.setMaxPoolSize(testConfig.getMaxPoolSize());
xaDataSource.setMaxLifetime(testConfig.getMaxLifetime());
xaDataSource.setBorrowConnectionTimeout(testConfig.getBorrowConnectionTimeout());
xaDataSource.setLoginTimeout(testConfig.getLoginTimeout());
xaDataSource.setMaintenanceInterval(testConfig.getMaintenanceInterval());
xaDataSource.setMaxIdleTime(testConfig.getMaxIdleTime());
xaDataSource.setTestQuery(testConfig.getTestQuery()); return xaDataSource; }
@Primary @Bean(name = "testSqlSessionFactory") public SqlSessionFactory
testSqlSessionFactory(@Qualifier("testDataSource") DataSource dataSource)
throws Exception { SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(dataSource); return bean.getObject(); } @Primary @Bean(name
= "testSqlSessionTemplate") public SqlSessionTemplate testSqlSessionTemplate(
@Qualifier("testSqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws
Exception { return new SqlSessionTemplate(sqlSessionFactory); } }
 
// basePackages 最好分开配置 如果放在同一个文件夹可能会报错 @Configuration @MapperScan(basePackages
= "cn.itcats.test2", sqlSessionTemplateRef = "test2SqlSessionTemplate") public
class TestMyBatisConfig2 { // 配置数据源 @Bean(name = "test2DataSource") public
DataSource testDataSource(DBConfig2 testConfig) throws SQLException {
MysqlXADataSource mysqlXaDataSource = new MysqlXADataSource();
mysqlXaDataSource.setUrl(testConfig.getUrl());
mysqlXaDataSource.setPinGlobalTxToPhysicalConnection(true);
mysqlXaDataSource.setPassword(testConfig.getPassword());
mysqlXaDataSource.setUser(testConfig.getUsername());
mysqlXaDataSource.setPinGlobalTxToPhysicalConnection(true);
AtomikosDataSourceBean xaDataSource = new AtomikosDataSourceBean();
xaDataSource.setXaDataSource(mysqlXaDataSource);
xaDataSource.setUniqueResourceName("test2DataSource");
xaDataSource.setMinPoolSize(testConfig.getMinPoolSize());
xaDataSource.setMaxPoolSize(testConfig.getMaxPoolSize());
xaDataSource.setMaxLifetime(testConfig.getMaxLifetime());
xaDataSource.setBorrowConnectionTimeout(testConfig.getBorrowConnectionTimeout());
xaDataSource.setLoginTimeout(testConfig.getLoginTimeout());
xaDataSource.setMaintenanceInterval(testConfig.getMaintenanceInterval());
xaDataSource.setMaxIdleTime(testConfig.getMaxIdleTime());
xaDataSource.setTestQuery(testConfig.getTestQuery()); return xaDataSource; }
@Bean(name = "test2SqlSessionFactory") public SqlSessionFactory
testSqlSessionFactory(@Qualifier("test2DataSource") DataSource dataSource)
throws Exception { SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(dataSource); return bean.getObject(); } @Bean(name =
"test2SqlSessionTemplate") public SqlSessionTemplate testSqlSessionTemplate(
@Qualifier("test2SqlSessionFactory") SqlSessionFactory sqlSessionFactory)
throws Exception { return new SqlSessionTemplate(sqlSessionFactory); } }
 

最后在springboot的App.java中配置注解   @EnableConfigurationProperties(value = {
DBConfig1.class, DBConfig2.class })

友情链接
KaDraw流程图
API参考文档
OK工具箱
云服务器优惠
阿里云优惠券
腾讯云优惠券
华为云优惠券
站点信息
问题反馈
邮箱:ixiaoyang8@qq.com
QQ群:637538335
关注微信