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.properties或application.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多数据源方法上方添加事务时数据源切换失败的问题。在实际开发中,可以根据具体业务需求,灵活使用多数据源和事务注解,确保系统数据一致性和可靠性。
希望本文对您有所帮助,如果您有任何问题或建议,欢迎在评论区留言!
本文来自极简博客,作者:浅笑安然,转载请注明原文链接:MyBatis-plus多数据源方法上方添加事务,数据源切换失败
微信扫一扫,打赏作者吧~