在 Spring 中配置多数据源 与 给多个数据源添加事物管理是有区别的。
如果只需要使用到多个数据源,而不需要进行事物管理,是可以进行简单处理的。
Spring 中配置多数据源
如果不需要对数据源进行事物管理的话,在 Spring 中配置多个数据源是相对比较容易的。
根据前面分析 多事务管理器&多数据源的处理,我们知道,如果使用 MyBatis 来操作 DB 的话,那么配置多数据源只需要两步:
1、定义 n 个数据源 DataSource
2、定义基于 DataSource 的 SqlSessionFactory (通过 MyBatis 操作 sql)
多数据源的配置示例如下:
// Master 数据源配置
@Configuration
@MapperScan(basePackages = "com.kvn.mapper.master", sqlSessionFactoryRef = "masterSqlSessionFactory")
public class MasterMybatisConfig {
@Bean("master")
@ConfigurationProperties(prefix = "spring.datasource.master")
public DataSource masterDataSource() {
return DataSourceBuilder.create().build();
}
@Bean("masterSqlSessionFactory")
public SqlSessionFactory masterSqlSessionFactory(@Qualifier("master") DataSource dataSource) throws Exception {
// 设置数据源
MybatisSqlSessionFactoryBean mybatisSqlSessionFactoryBean = new MybatisSqlSessionFactoryBean();
mybatisSqlSessionFactoryBean.setDataSource(dataSource);
// mapper 的xml文件位置
PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
String locationPattern = "classpath*:/mapper/master/*.xml";
mybatisSqlSessionFactoryBean.setMapperLocations(resolver.getResources(locationPattern));
// 对应数据库的 entity 位置
String typeAliasesPackage = "com.kvn.entity.master";
mybatisSqlSessionFactoryBean.setTypeAliasesPackage(typeAliasesPackage);
return mybatisSqlSessionFactoryBean.getObject();
}
}
------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------
// Slave 数据源配置
@Configuration
@MapperScan(basePackages = "com.kvn.mapper.slave", sqlSessionFactoryRef = "masterSqlSessionFactory")
public class SlaveMybatisConfig {
@Bean("slave")
@ConfigurationProperties(prefix = "spring.datasource.slave")
public DataSource slaveDataSource() {
return DataSourceBuilder.create().build();
}
@Bean("slaveSqlSessionFactory")
public SqlSessionFactory masterSqlSessionFactory(@Qualifier("slave") DataSource dataSource) throws Exception {
// 设置数据源
MybatisSqlSessionFactoryBean mybatisSqlSessionFactoryBean = new MybatisSqlSessionFactoryBean();
mybatisSqlSessionFactoryBean.setDataSource(dataSource);
// mapper 的xml文件位置
PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
String locationPattern = "classpath*:/mapper/master/*.xml";
mybatisSqlSessionFactoryBean.setMapperLocations(resolver.getResources(locationPattern));
// 对应数据库的 entity 位置
String typeAliasesPackage = "com.kvn.entity.slave";
mybatisSqlSessionFactoryBean.setTypeAliasesPackage(typeAliasesPackage);
return mybatisSqlSessionFactoryBean.getObject();
}
}
Spring 中配置多数据源的事物管理
如果要给数据源添加添加事物管理的功能的话,那么就需要在多数据源配置的基础之上,再给每个 DataSource 添加事物管理器(TransactionManager),同时,开启对 @Transactional 方法的拦截。
所以,配置多数据源的事物管理的步骤如下:
1、定义 n 个数据源 DataSource
2、定义基于 DataSource 的 SqlSessionFactory (通过 MyBatis 操作 sql)
3、定义基于 DataSource 的 TransactionManager(事物管理器)
4、通过 @EnableTransactionManagement
来开启对 @Transactional
方法的拦截
多数据源的事物管理配置示例如下:
// Master 数据源配置
@Configuration
@MapperScan(basePackages = "com.kvn.mapper.master", sqlSessionFactoryRef = "masterSqlSessionFactory")
public class MasterMybatisConfig {
@Bean("master")
@ConfigurationProperties(prefix = "spring.datasource.master")
public DataSource masterDataSource() {
return DataSourceBuilder.create().build();
}
/**
* 创建 master 数据源的事物管理器
*/
@Bean(name = "masterTxManager")
public PlatformTransactionManager masterTxManager(@Qualifier("master") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
@Bean("masterSqlSessionFactory")
public SqlSessionFactory masterSqlSessionFactory(@Qualifier("master") DataSource dataSource) throws Exception {
// 设置数据源
MybatisSqlSessionFactoryBean mybatisSqlSessionFactoryBean = new MybatisSqlSessionFactoryBean();
mybatisSqlSessionFactoryBean.setDataSource(dataSource);
// mapper 的xml文件位置
PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
String locationPattern = "classpath*:/mapper/master/*.xml";
mybatisSqlSessionFactoryBean.setMapperLocations(resolver.getResources(locationPattern));
// 对应数据库的 entity 位置
String typeAliasesPackage = "com.kvn.entity.master";
mybatisSqlSessionFactoryBean.setTypeAliasesPackage(typeAliasesPackage);
return mybatisSqlSessionFactoryBean.getObject();
}
}
------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------
// Slave 数据源配置
@Configuration
@MapperScan(basePackages = "com.kvn.mapper.slave", sqlSessionFactoryRef = "masterSqlSessionFactory")
public class SlaveMybatisConfig {
@Bean("slave")
@ConfigurationProperties(prefix = "spring.datasource.slave")
public DataSource slaveDataSource() {
return DataSourceBuilder.create().build();
}
/**
* 创建 slave 数据源的事物管理器
*/
@Bean(name = "slaveTxManager")
public PlatformTransactionManager slaveTxManager(@Qualifier("slave") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
@Bean("slaveSqlSessionFactory")
public SqlSessionFactory masterSqlSessionFactory(@Qualifier("slave") DataSource dataSource) throws Exception {
// 设置数据源
MybatisSqlSessionFactoryBean mybatisSqlSessionFactoryBean = new MybatisSqlSessionFactoryBean();
mybatisSqlSessionFactoryBean.setDataSource(dataSource);
// mapper 的xml文件位置
PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
String locationPattern = "classpath*:/mapper/master/*.xml";
mybatisSqlSessionFactoryBean.setMapperLocations(resolver.getResources(locationPattern));
// 对应数据库的 entity 位置
String typeAliasesPackage = "com.kvn.entity.slave";
mybatisSqlSessionFactoryBean.setTypeAliasesPackage(typeAliasesPackage);
return mybatisSqlSessionFactoryBean.getObject();
}
}
小结
抽象出来看的话,在 Spring 中配置多数据源,其实就是定义多个 DataSource
的 bean。
而配置多数据源的事物管理,就是在多个 DataSource
bean 的基础之上,再为每个 DataSource
添加 TransactionManager
事物管理器。
附:
PlatformTransactionManager 是 Spring 事务实现的核心接口。它提供了三个方法用来管理事务:
1、 getTransaction(TransactionDefinition)
2、 commit(TransactionStatus)
3、 rollback(TransactionStatus)PlatformTransactionManager 提供了管理事物的能力,而对 @Transactional 事物方法拦截的处理是通过
@EnableTransactionManagement
来开启的。@EnableTransactionManagement
的作用是自动注册 BeanFactoryTransactionAttributeSourceAdvisor,让 TransactionInterceptor 来拦截 @Transactional 标记的方法。所以,
PlatformTransactionManager
与@EnableTransactionManagement
的共同作用下,让 Spring 拥有了对 @Transactional 标记的方法进行事物管理的能力。