V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
coderstory
V2EX  ›  Java

spring boot 实现多数据源 JdbcTemplate 的内部缓存怎么解决?

  •  
  •   coderstory ·
    coderstory · 2021-11-02 19:49:51 +08:00 · 2220 次点击
    这是一个创建于 1146 天前的主题,其中的信息可能已经有所发展或是发生改变。

    现在有个 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 了。

    不知道还有没有更好的解决访问。

    10 条回复    2021-11-17 13:50:23 +08:00
    nonoyang
        1
    nonoyang  
       2021-11-02 20:27:06 +08:00 via iPad
    最暴力的,注册多个不同数据源的 Bean 就可以解决你注入依赖的问题了吧
    xuanbg
        2
    xuanbg  
       2021-11-03 08:42:50 +08:00
    都多数据源了,干脆微服务好了。
    857681664
        3
    857681664  
       2021-11-03 09:08:15 +08:00 via Android
    不嫌麻烦的话可以自己 getconnection ,之后所有操作都通过 connection 做
    chendy
        4
    chendy  
       2021-11-03 09:14:10 +08:00
    直接配多个数据源 + 多个 JdbcTemplate
    cheng6563
        5
    cheng6563  
       2021-11-03 09:29:04 +08:00
    AbstractRoutingDataSource 都能写,再写个 AbstractRoutingJdbcTemplate 不就行了
    tenserG
        6
    tenserG  
       2021-11-03 10:12:23 +08:00
    注册多个不同数据源的 Bean,手头项目就是这么做的..
    git00ll
        7
    git00ll  
       2021-11-03 10:39:41 +08:00   ❤️ 1
    你这个是在同一事物内的逻辑吧,把事务去掉看
    ColinLi
        8
    ColinLi  
       2021-11-03 15:16:18 +08:00
    根据 entityManager 获取 DataSource ,然后再 new NamedParameterJdbcTemplate(getDataSource(entityManager))
    coderstory
        9
    coderstory  
    OP
       2021-11-03 16:41:38 +08:00
    @git00ll 非常正确。。同一个事物里出现了多个数据源导致炸了
    Aresxue
        10
    Aresxue  
       2021-11-17 13:50:23 +08:00
    真实原因是使用了事务,这要求实现单应用内的分布式事务,可以依赖 JTA 去做,比如 Atomikos 、Bitronix 都是不错的开源的 JTA 实现,我这边是实现了一个 DynamicTransactional 注解,多数据源的事务使用我这个注解,依赖注解的切面里使用 JTA(这里我用的是 seata)维护了多数据源下的分布式事务
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   969 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 19:01 · PVG 03:01 · LAX 11:01 · JFK 14:01
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.