关于动态切换数据源的问题

2022-09-22 13:53:19 +08:00
 7911364440

目前使用的是 AbstractRoutingDataSource+AOP 动态切换数据源,现在有个需求要在一个请求中分别对 A 库和 B 库各新增一条数据。

伪代码如下:


public class FooController {

	
    @PostMapping(value = "/foo")
    public void foo() {
    	// AOP 会拦截这两个 service 中的方法,然后切换数据源
    	fooService.save();	// 在 A 库插入数据,这里是正常的
        barService.save();  // 在 B 库插入数据,这里切换不了数据源,使用的还是 A 数据源
    }
    
}

问题是只有第一个方法切换数据源有效,第二个方法切换不了数据源。
应该是第二个方法切换数据源之后,没有触发下面这段方法,想问下有没有其它解决方案?


public class DynamicDataSource extends AbstractRoutingDataSource {

    @Override
    protected Object determineCurrentLookupKey() {
        return DynamicDataSourceHolder.getKey();
    }
    
}

PS:orm 框架用的 jpa

2212 次点击
所在节点    Java
15 条回复
nekolr
2022-09-22 14:37:43 +08:00
建议贴一下 aop 的相关代码
wolfie
2022-09-22 14:47:27 +08:00
注掉 fooService 看看,能不能走 AOP 。
Kaiv2
2022-09-22 14:50:32 +08:00
需求是什么?
joooooker21
2022-09-22 14:53:10 +08:00
DynamicDataSourceHolder.setKey( b )
sirierx
2022-09-22 14:54:33 +08:00
baomidou.dynamic.datasource
7911364440
2022-09-22 15:13:07 +08:00
@wolfie 两个 service 都是可以被 aop 拦截的
wolfie
2022-09-22 16:20:57 +08:00
贴部分代码吧。
在看看有没有涉及到 异步 相关的东西。
cheng6563
2022-09-22 16:25:07 +08:00
第二个方法必须要启动新事物,不然事务管理器会保持连接
so2back
2022-09-22 16:36:50 +08:00
需要切换数据源的方法用 @Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)注解试试,也就是按楼上说的,需要起一个新的事务
7911364440
2022-09-22 17:14:47 +08:00
@cheng6563
@so2back
在两个 service 都加上了 @Transactional(propagation = Propagation.REQUIRES_NEW) 也不行
MrZYB
2022-09-22 17:26:06 +08:00
切换数据源写个 setDataSource 方法,在调用第 2 个 service.save()时手动切换数据源。
git00ll
2022-09-22 17:33:00 +08:00
AbstractPlatformTransactionManager 类上有一个 setTransactionSynchronization 方法,可以控制不是真实事物情况下,是否需要使用事务管理器进行连接同步。

可选值为
SYNCHRONIZATION_ALWAYS ,SYNCHRONIZATION_ON_ACTUAL_TRANSACTION ,SYNCHRONIZATION_NEVER 三个字段。

你这里的情况,把事务管理器上的 setTransactionSynchronization 设为 SYNCHRONIZATION_ON_ACTUAL_TRANSACTION ,试试看
czn6mx
2022-09-22 19:18:50 +08:00
AOP after 清掉 ThreadLocal dataSourceKey
cslive
2022-09-23 08:56:21 +08:00
jpa 不需要 aop 切换,需要单独设置每个数据源针对的实体类所在的位置
Aresxue
2022-10-08 11:23:18 +08:00
生产级代码就别自己写了,用 https://github.com/baomidou/dynamic-datasource-spring-boot-starter 这个好了,唯一要注意的是分布式事务的部分需要自己重写一下,如果是为了学习也可以看一下人家的代码,也是 AbstractRoutingDataSource 这个路子

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/882132

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX