MyBatis-plus多数据源方法上方添加事务,数据源切换失败

 
更多

1. 引言

MyBatis-plus是一个优秀的Java持久层框架,在实际开发中经常使用到多数据源的配置。然而,当在多数据源的方法上方添加事务注解时,可能会出现数据源切换失败的问题。本文将介绍如何解决这个问题,确保在添加事务注解的同时成功切换数据源。

2. 问题描述

在使用MyBatis-plus进行多数据源配置时,我们通常会在方法上方添加事务注解,如@Transactional。但在这种情况下,可能会出现数据源切换失败的问题,即事务以错误的数据源进行操作,导致数据不一致的情况发生。

3. 问题原因

出现数据源切换失败的问题,主要是由于事务注解的失效导致的。当我们在方法上添加事务注解时,Spring会对该方法进行AOP增强,将事务逻辑织入到方法中。但是,MyBatis-plus的数据源切换是通过ThreadLocal实现的,而Spring的事务是通过AOP动态代理实现的。由于MyBatis-plus和Spring事务的实现方式不同,导致事务注解失效。

4. 解决方法

要解决这个问题,我们需要在方法上方添加事务注解的同时,手动进行数据源切换。以下是解决方法的步骤:

4.1 引入依赖

首先,在pom.xml文件中引入MyBatis-plus和Spring事务管理器的依赖。

<dependency>
  <groupId>com.baomidou</groupId>
  <artifactId>mybatis-plus-boot-starter</artifactId>
  <version>最新版本号</version>
</dependency>

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-data-jpa</artifactId>
  <version>最新版本号</version>
</dependency>

4.2 配置多数据源

然后,在application.propertiesapplication.yml文件中配置多数据源信息。

spring:
  datasource:
    dynamic:
      primary: db1
      datasource:
        db1:
          driver-class-name: com.mysql.jdbc.Driver
          url: jdbc:mysql://localhost:3306/db1
          username: root
          password: 123456

        db2:
          driver-class-name: com.mysql.jdbc.Driver
          url: jdbc:mysql://localhost:3306/db2
          username: root
          password: 123456

4.3 配置数据源切换

MyDataSourceConfig类中配置数据源切换的逻辑。

@Configuration
public class MyDataSourceConfig {

    @Bean
    @Primary
    @ConfigurationProperties("spring.datasource.dynamic.datasource.db1")
    public DataSource db1DataSource() {
        return DataSourceBuilder.create().build();
    }

    @Bean
    @ConfigurationProperties("spring.datasource.dynamic.datasource.db2")
    public DataSource db2DataSource() {
        return DataSourceBuilder.create().build();
    }

    @Bean
    public DataSourceRouting dataSource(@Qualifier("db1DataSource") DataSource db1DataSource,
                                        @Qualifier("db2DataSource") DataSource db2DataSource) {
        Map<Object, Object> targetDataSources = new HashMap<>();
        targetDataSources.put("db1", db1DataSource);
        targetDataSources.put("db2", db2DataSource);

        DataSourceRouting dataSourceRouting = new DataSourceRouting();
        dataSourceRouting.setTargetDataSources(targetDataSources);
        dataSourceRouting.setDefaultTargetDataSource(db1DataSource);

        return dataSourceRouting;
    }

    @Bean
    public PlatformTransactionManager transactionManager(DataSourceRouting dataSourceRouting) {
        return new DataSourceTransactionManager(dataSourceRouting);
    }
}

4.4 实现数据源切换

DataSourceRouting类中实现数据源切换的逻辑。

public class DataSourceRouting extends AbstractRoutingDataSource {
    // 重写determineCurrentLookupKey方法,返回当前数据源的key
    @Override
    protected Object determineCurrentLookupKey() {
        return DataSourceContextHolder.getDataSource();
    }
}

4.5 实现事务注解切面

TransactionAspect类中实现事务注解的切面逻辑。

@Aspect
@Component
public class TransactionAspect {

    @Around("@annotation(org.springframework.transaction.annotation.Transactional)")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        try {
            // 获取数据源
            MethodSignature signature = (MethodSignature) joinPoint.getSignature();
            Method method = signature.getMethod();
            DataSourceSwitch dataSourceSwitch = method.getAnnotation(DataSourceSwitch.class);
            if (dataSourceSwitch != null) {
                DataSourceContextHolder.setDataSource(dataSourceSwitch.value());
            }

            return joinPoint.proceed();
        } finally {
            // 清理数据源
            DataSourceContextHolder.clearDataSource();
        }
    }
}

4.6 使用自定义注解

最后,在方法上使用自定义的注解@DataSourceSwitch进行数据源切换。

@Service
public class UserService {

    @DataSourceSwitch("db1")
    @Transactional
    public void addUser(User user) {
        // 添加用户逻辑
    }

    @DataSourceSwitch("db2")
    @Transactional
    public void updateUser(User user) {
        // 更新用户逻辑
    }
}

5. 结论

通过以上步骤,我们成功解决了MyBatis-plus多数据源方法上方添加事务时数据源切换失败的问题。在实际开发中,可以根据具体业务需求,灵活使用多数据源和事务注解,确保系统数据一致性和可靠性。

希望本文对您有所帮助,如果您有任何问题或建议,欢迎在评论区留言!

打赏

本文固定链接: https://www.cxy163.net/archives/7712 | 绝缘体

该日志由 绝缘体.. 于 2021年02月26日 发表在 未分类 分类下, 你可以发表评论,并在保留原文地址及作者的情况下引用到你的网站或博客。
原创文章转载请注明: MyBatis-plus多数据源方法上方添加事务,数据源切换失败 | 绝缘体
关键字: , , , ,

MyBatis-plus多数据源方法上方添加事务,数据源切换失败:等您坐沙发呢!

发表评论


快捷键:Ctrl+Enter