项目场景:
提示:这里简述项目相关背景:
多数据源导致yml配置失效以及事务失效
问题一描述
提示:这里描述项目中遇到的问题:
今天在修改项目的时候发现公司还是在用这个去映射实体类,我觉得不太方便,然后去yml里新增mybatis的配置,但是配置之后发现数据库中驼峰列没办法映射到实体类中
在DataSouceConfig中新增这段代码即可解决,问题是由于配置多数据源时,application.yml 的有关mybatis的配置是失效的,因为他不知道配置哪一个数据源
//定义全局配置
@Bean
@ConfigurationProperties(prefix = "mybatis.configuration")
public org.apache.ibatis.session.Configuration configuration(){
return new org.apache.ibatis.session.Configuration();
}
@Bean(name = "sqlSessionFactory")
@Primary
public SqlSessionFactory sqlSessionFactory(@Qualifier("OadbDataSource") DruidDataSource dataSource,org.apache.ibatis.session.Configuration configuration) throws Exception {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
/** 配置初始化大小、最小、最大 */
dataSource.setInitialSize(initialSize);
dataSource.setMaxActive(maxActive);
dataSource.setMinIdle(minIdle);
/** 配置获取连接等待超时的时间 */
dataSource.setMaxWait(maxWait);
bean.setDataSource(dataSource);
bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:workplan/mybatis/mapper/oa/*.xml"));
bean.setConfiguration(configuration);
return bean.getObject();
}
问题二描述:
提示:这里填写问题的分析:
还有一个就是多数据导致的事务失效问题,我在测试是发现我添加了@Transactional注解但是事务还是不生效
解决方案:
提示:这里填写该问题的具体解决方案:
在多数据源配置中,事务管理确实是一个需要特别注意的问题。为了确保事务在多数据源环境中正常工作,需要配置不同的事务管理器,并确保它们正确绑定到相应的数据源。
以下是一个示例,展示了如何在多数据源配置中正确配置事务管理,以确保事务不会失效。
配置数据源
@Configuration
public class DataSourceConfig {
@Primary
@Bean(name = "primaryDataSource")
@ConfigurationProperties(prefix = "spring.datasource.primary")
public DataSource primaryDataSource() {
return DataSourceBuilder.create().build();
}
@Bean(name = "secondaryDataSource")
@ConfigurationProperties(prefix = "spring.datasource.secondary")
public DataSource secondaryDataSource() {
return DataSourceBuilder.create().build();
}
}
配置mybatis和事务管理器
@MapperScan(basePackages = "com.example.mapper.primary", sqlSessionFactoryRef = "primarySqlSessionFactory", transactionManagerRef = "primaryTransactionManager")
@Configuration
public class PrimaryMyBatisConfig {
@Primary
@Bean(name = "primarySqlSessionFactory")
public SqlSessionFactory primarySqlSessionFactory(@Qualifier("primaryDataSource") DataSource dataSource) throws Exception {
SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
factoryBean.setDataSource(dataSource);
return factoryBean.getObject();
}
@Primary
@Bean(name = "primaryTransactionManager")
public DataSourceTransactionManager primaryTransactionManager(@Qualifier("primaryDataSource") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
@Primary
@Bean(name = "primarySqlSessionTemplate")
public SqlSessionTemplate primarySqlSessionTemplate(@Qualifier("primarySqlSessionFactory") SqlSessionFactory sqlSessionFactory) {
return new SqlSessionTemplate(sqlSessionFactory);
}
}
@MapperScan(basePackages = "com.example.mapper.secondary", sqlSessionFactoryRef = "secondarySqlSessionFactory", transactionManagerRef = "secondaryTransactionManager")
@Configuration
public class SecondaryMyBatisConfig {
@Bean(name = "secondarySqlSessionFactory")
public SqlSessionFactory secondarySqlSessionFactory(@Qualifier("secondaryDataSource") DataSource dataSource) throws Exception {
SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
factoryBean.setDataSource(dataSource);
return factoryBean.getObject();
}
@Bean(name = "secondaryTransactionManager")
public DataSourceTransactionManager secondaryTransactionManager(@Qualifier("secondaryDataSource") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
@Bean(name = "secondarySqlSessionTemplate")
public SqlSessionTemplate secondarySqlSessionTemplate(@Qualifier("secondarySqlSessionFactory") SqlSessionFactory sqlSessionFactory) {
return new SqlSessionTemplate(sqlSessionFactory);
}
}
启动事务管理器
@EnableTransactionManagement
@SpringBootApplication
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
说明
配置数据源:
定义两个数据源,并分别使用不同的配置前缀。
使用 @Primary 注解标记主要数据源和主要事务管理器。
配置 MyBatis 和事务管理器:
每个数据源单独配置 SqlSessionFactory、SqlSessionTemplate 和 DataSourceTransactionManager。
使用 @Primary 注解标记主要的 MyBatis 配置和事务管理器。
在 @MapperScan 注解中,指定对应的 sqlSessionFactoryRef 和 transactionManagerRef。
启用事务管理:
使用 @EnableTransactionManagement 注解启用 Spring 的事务管理。
通过以上配置,可以确保在多数据源环境中,事务管理器能够正确地绑定到相应的数据源,确保事务不会失效。如果需要在一个事务中操作多个数据源,可以考虑使用分布式事务管理工具,如 Atomikos、Bitronix 或 Spring Cloud Sleuth。
- 注意 :DataSourceBuilder.create().build(); new HikariDataSource(); 这两种创建数据源的方式他们是有区别的
DataSourceBuilder.create().build()
DataSourceBuilder 是 Spring 提供的一个便捷类,用于通过配置文件创建数据源。
它允许你从 application.properties 或 application.yml 中读取数据源配置,并创建一个通用的 DataSource 实例。
它可以创建多种数据源实现,具体取决于你的依赖配置。
优点
简单易用,适合从配置文件中加载数据源配置。
能够根据类路径中的依赖自动选择适当的数据源实现。
提供了一致的接口来创建各种类型的数据源。
缺点
灵活性较低,依赖于配置文件中的配置。
对于特定的数据源实现(如 HikariCP),可能需要额外的配置来进行高级设置。
示例
@Configuration
public class DataSourceConfig {
@Primary
@Bean(name = "primaryDataSource")
@ConfigurationProperties(prefix = "spring.datasource.primary")
public DataSource primaryDataSource() {
return DataSourceBuilder.create().build();
}
@Bean(name = "secondaryDataSource")
@ConfigurationProperties(prefix = "spring.datasource.secondary")
public DataSource secondaryDataSource() {
return DataSourceBuilder.create().build();
}
}
new HikariDataSource()
HikariDataSource 是 HikariCP 提供的专用数据源实现。
它是一个高性能的 JDBC 连接池实现,提供了丰富的配置选项和出色的性能。
优点
高性能,HikariCP 被认为是目前最快的连接池实现之一。
提供了详细的配置选项,允许你对连接池进行精细化控制。
支持高级功能,如自定义连接测试、连接超时配置等。
缺点
需要手动配置,如果使用配置文件加载可能需要额外代码。
仅适用于 HikariCP,不如 DataSourceBuilder 那样通用。
示例
@Configuration
public class DataSourceConfig {
@Primary
@Bean(name = "primaryDataSource")
@ConfigurationProperties(prefix = "spring.datasource.primary")
public HikariDataSource primaryDataSource() {
return new HikariDataSource();
}
@Bean(name = "secondaryDataSource")
@ConfigurationProperties(prefix = "spring.datasource.secondary")
public HikariDataSource secondaryDataSource() {
return new HikariDataSource();
}
}
区别总结
创建方式:
DataSourceBuilder.create().build(): 使用 Spring 提供的通用构建器从配置文件中创建数据源。
new HikariDataSource(): 直接创建一个 HikariCP 数据源实例。
灵活性:
DataSourceBuilder.create().build(): 更加通用,能够根据类路径中的依赖选择适当的数据源实现。
new HikariDataSource(): 专用于 HikariCP,提供更高的性能和更多的配置选项。
性能和配置:
DataSourceBuilder.create().build(): 适合于一般场景,但对于性能和配置要求较高的场景可能不够灵活。
new HikariDataSource(): 提供更高的性能和详细的配置选项,适合高并发、高性能需求的场景。
选择哪种方式取决于你的具体需求。如果你需要高性能和详细的配置控制,可以选择 new HikariDataSource()。如果你需要更通用、更简单的配置方式,可以选择 DataSourceBuilder.create().build()
假设你才用的是HikariDataSource则在配置事务管理器时需要正确配置事务管理器和数据源
@Configuration
@EnableTransactionManagement
public class DataSourceConfig {
@Primary
@Bean(name = "primaryDataSource")
@ConfigurationProperties(prefix = "spring.datasource.primary")
public HikariDataSource primaryDataSource() {
return new HikariDataSource();
}
@Bean(name = "secondaryDataSource")
@ConfigurationProperties(prefix = "spring.datasource.secondary")
public HikariDataSource secondaryDataSource() {
return new HikariDataSource();
}
@Primary
@Bean(name = "primaryTransactionManager")
public DataSourceTransactionManager primaryTransactionManager(@Qualifier("primaryDataSource") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
@Bean(name = "secondaryTransactionManager")
public DataSourceTransactionManager secondaryTransactionManager(@Qualifier("secondaryDataSource") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
}
使用@Transactional注解
在使用 @Transactional 时,可以指定要使用的事务管理器。如果不指定,Spring 将使用默认的(通常是 @Primary 标记的)事务管理器。
@Service
public class MyService {
@Transactional("primaryTransactionManager")
public void primaryTransactionMethod() {
// primary data source operations
}
@Transactional("secondaryTransactionManager")
public void secondaryTransactionMethod() {
// secondary data source operations
}
}
- 注意:
1.确保每个数据源有独立的事务管理器:
- 每个数据源都应该有自己的 DataSourceTransactionManager,并在使用时明确指定。
2.启用事务管理:
- 使用 @EnableTransactionManagement 注解启用事务管理。
3.正确使用 @Transactional 注解:
- 在使用 @Transactional 时,明确指定要使用的事务管理器,以避免混淆。