
现在有个 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 你这个是在同一事物内的逻辑吧,把事务去掉看 |
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)维护了多数据源下的分布式事务 |