springboot项目,使用ORM层面使用 mybatis-plus,并且集成了 dynamic-datasource-spring-boot-starter 实现多个数据源的切换。
yml文件中 按照格式 配置了2个数据库 ds1、ds2 ,在Mapper接口 标记上 @DS(“ds2”),但实际执行时,却使用了 ds1的数据库,导致了sql报错。
经过调试发现,获取数据库链接的 调用链路大致如下
org.springframework.jdbc.datasource.DataSourceUtils#getConnection
org.springframework.jdbc.datasource.DataSourceUtils#doGetConnection (DataSource dataSource)
org.springframework.transaction.support.TransactionSynchronizationManager#getResource(Object key)
。 该方法中的参数是 com.baomidou.dynamic.datasource.DynamicRoutingDataSource
的一个实例对象,作为key从一个Map中获取缓存的链接。而缓存中的连接是ds1 的连接。从现象上看,这是一个 数据库连接缓存 没有 按照数据源进行 分别存放 的bug。但是否是别的原因导致了这种现象,还无法确定,因为这个bug太严重了,不应该没有被发现。
最终发现是测试用例中 @Transactional 注解导致的问题。执行测试用例时,会提前创建好一个Connection并放入缓存,框架对这种情况没有处理好,直接使用了缓存中的连接,没有动态根据数据源创建连接。