springboot+mybatis多数据源配置时出现事务及配置文件失效问题

项目场景:

提示:这里简述项目相关背景:

多数据源导致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 时,明确指定要使用的事务管理器,以避免混淆。
  • 23
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
要实现SpringBoot Mybatis多数据源,需要添加以下依赖: 1. Mybatis-spring-boot-starter:Mybatis Spring Boot的官方启动器,包含了 MybatisSpring Boot 的核心依赖。 2. MySQL Connector/J:MySQL的Java驱动程序,用于连接MySQL数据库。 3. Druid:阿里巴巴的数据库连接池,支持高并发、高可用的特性。 4. SpringBoot JDBC:Spring Boot的JDBC组件,用于支持多数据源。 5. SpringBoot Data Redis:Spring Boot的Redis组件,用于支持Redis缓存。 6. SpringBoot Actuator:Spring Boot的监控组件,用于监控应用程序的运行情况。 依赖配置如下: ``` <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.1.4</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.22</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> <version>1.2.6</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> ``` 需要注意的是,Druid的版本需要与Mybatis的版本匹配,可以在Mybatis官网上查看对应关系。此外,配置多数据源,需要在 application.properties 或 application.yml 中进行配置,具体配置方式可以参考 Spring Boot 官方文档。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值