spring boot 实现多数据源 JdbcTemplate 的内部缓存怎么解决? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
coderstory
V2EX    Java

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

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

    现在有个 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     Solana     1168 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 29ms UTC 17:48 PVG 01:48 LAX 09:48 JFK 12:48
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86