DynamicDataSource动态切换更改数据库失效的问题

@Transaction注解导致动态切换更改数据库失效

由于自己练习dynamic-datasource的使用 写的不规范没有按照MVC分层直接在controller上加@Transaction 导致切库一直不成功。

在这里插入图片描述
当我们在controller上加@Transaction注解时,我们设置key 的时候下面方法已经执行,导致获取的key一直是默认的。所以切库失败。
在这里插入图片描述
把@Transaction注解写在service上切库就成功。

### MyBatis-Plus 中 `@DS` 注解失效解决方案 #### 数据源切换机制分析 在 Spring Boot 和 MyBatis-Plus 的多数据源配置中,`@DS` 注解用于指定当前操作应使用的数据库连接。然而,在某些情况下,此注解可能无法正常工作。 当遇到 `@DS` 注解失效的情况时,通常是因为事务管理器的影响或是访问控制符的问题。具体来说: - 如果方法被声明为 `protected` 或者其他非公共访问级别,则可能导致 `@DS` 注解生效[^4]。 - 当存在全局或局部事务时,可能会覆盖掉由 `@DS` 设置的数据源上下文,从而导致实际查询仍然指向默认数据源[^3]。 #### 解决方案一:调整访问修饰符 对于因访问修饰符引起的 `@DS` 失效问题,可以尝试将受影响的方法改为 `public` 访问级别。这有助于确保 AOP 切面能够正确识别并处理这些带有 `@DS` 注解的方法调用。 ```java // 修改前 protected void someMethod() { // ... } // 修改后 public void someMethod() { // ... } ``` #### 解决方案二:分离事务边界 针对由于事务引起的数据源切换失败情况,建议重新设计业务逻辑流程,使得涉及同数据源的操作在同一个事务范围内完成。可以通过创建独立的服务类来分别封装对各个库的操作,并各自加上合适的事务属性。 ```java @Service @Transactional(propagation = Propagation.REQUIRES_NEW) public class DataSourceAService { public void operateOnDataSourceA(){ // 对 data source A 进行操作... } } @Service @Transactional(propagation = Propagation.REQUIRES_NEW) public class DataSourceBService { public void operateOnDataSourceB(){ // 对 data source B 进行操作... } } ``` 此外,还可以考虑使用编程方式手动开启新事务,以绕过原有事务对外部数据源的选择干扰。 #### 解决方案三:自定义数据源切换策略 如果上述两种办法都能解决问题,那么就需要深入研究现有的动态数据源实现原理,甚至编写自己的数据源路由算法。通过继承 `AbstractRoutingDataSource` 类来自定义数据源选择规则,并将其注册到应用程序上下文中作为主要数据源提供者。 ```java @Component public class DynamicDataSource extends AbstractRoutingDataSource { private static final ThreadLocal<String> contextHolder = new ThreadLocal<>(); @Override protected Object determineCurrentLookupKey() { return getContext(); } public static void setContext(String dataSourceName){ contextHolder.set(dataSourceName); } public static String getContext(){ return Optional.ofNullable(contextHolder.get()).orElse("default"); } public static void clearContext(){ contextHolder.remove(); } } ``` 最后,在每次需要改变目标数据源之前调用 `DynamicDataSource.setContext()` 方法传入相应的名称;完成后记得清理线程变量以防内存泄漏。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值