现在有个 spring boot 2.x 项目
创建了一个 AbstractRoutingDataSource 的实现类,以便动态切换数据源
而数据库访问使用了 JdbcTemplate 。
实际使用的过程中,发现 JdbcTemplate 第二次以及之后的数据源切换不生效 查看 JdbcTemplate 的源码发现 JdbcTemplate 内部实现了 connection 缓存,导致第二次访问的时候,直接拿了缓存的 connection ,而不是访问 datasource 获取。
ConnectionHolder conHolder = (ConnectionHolder) TransactionSynchronizationManager.getResource(dataSource);
if (conHolder != null && (conHolder.hasConnection() || conHolder.isSynchronizedWithTransaction())) {
conHolder.requested();
if (!conHolder.hasConnection()) {
logger.debug("Fetching resumed JDBC Connection from DataSource");
conHolder.setConnection(fetchConnection(dataSource));
}
return conHolder.getConnection();
}
这样导致了动态数据源功能只能实现一次,第一次确定数据源之后一直是这个。 百度个谷歌了一下,发现都是通过直接 new 一个 JdbcTemplate ,然后在构造函数里塞了一个 datasource 实现的, 但这样就不能依赖注入 JdbcTemplate 了。
不知道还有没有更好的解决访问。
1
nonoyang 2021-11-02 20:27:06 +08:00 via iPad
最暴力的,注册多个不同数据源的 Bean 就可以解决你注入依赖的问题了吧
|
2
xuanbg 2021-11-03 08:42:50 +08:00
都多数据源了,干脆微服务好了。
|
3
857681664 2021-11-03 09:08:15 +08:00 via Android
不嫌麻烦的话可以自己 getconnection ,之后所有操作都通过 connection 做
|
4
chendy 2021-11-03 09:14:10 +08:00
直接配多个数据源 + 多个 JdbcTemplate
|
5
cheng6563 2021-11-03 09:29:04 +08:00
AbstractRoutingDataSource 都能写,再写个 AbstractRoutingJdbcTemplate 不就行了
|
6
tenserG 2021-11-03 10:12:23 +08:00
注册多个不同数据源的 Bean,手头项目就是这么做的..
|
7
git00ll 2021-11-03 10:39:41 +08:00 1
你这个是在同一事物内的逻辑吧,把事务去掉看
|
8
ColinLi 2021-11-03 15:16:18 +08:00
根据 entityManager 获取 DataSource ,然后再 new NamedParameterJdbcTemplate(getDataSource(entityManager))
|
9
coderstory OP @git00ll 非常正确。。同一个事物里出现了多个数据源导致炸了
|
10
Aresxue 2021-11-17 13:50:23 +08:00
真实原因是使用了事务,这要求实现单应用内的分布式事务,可以依赖 JTA 去做,比如 Atomikos 、Bitronix 都是不错的开源的 JTA 实现,我这边是实现了一个 DynamicTransactional 注解,多数据源的事务使用我这个注解,依赖注解的切面里使用 JTA(这里我用的是 seata)维护了多数据源下的分布式事务
|