本来想用springboot+mybatis作多数据源的切换方案,想经过借鉴网上现有的方案,结果搜索后大量都是使用AbstractRoutingDataSource多数据源方案,经过实践后,发现若是声明了事务,将会在事务内部切换数据源失败。结果,就是debug,看源码找缘由。下面是springboot+mybatis的调用栈,若是有点功力的同窗们一看就知道了。spring
存在transaction状况下 @Transactional切面切入拦截 DataSourceTransactionManager doBegin 从threadlocal holder中获取connection 获取不到 获取链接 AbstractRoutingDataSource#getConnection 封装holder,存入threadLocal中,key为AbstractRoutingDataSource 获取到,再也不AbstractRoutingDataSource#getConnection 此时,已经获取到connection,若是@Transactional注解还有切换数据源的切面,则使用切面中切换好的数据源,若是没有其余注解,则得到配置的defaultDataSource的数据源。 ======================= step2 =============================== 以后,调用mybatis的mapper mybatis Executor prepareStatement getConnection() SpringManagedTransaction getConnection() 查看threadLocal中,key为AbstractRoutingDataSource,取出connection的holder 若是有用holder里面的connection 若是没有从AbstractRoutingDataSource获取新的链接 ======================= step3 ==================================== @Transactional注解的方法中还在调用其余须要切换数据源的service或者方法 仍然走step2,因为从threadLocal能够获取到connection,因此不会从AbstractRoutingDataSource获取新的链接,也就是切换数据源失败
这里的AbstractRoutingDataSource#getConnection方法是切换数据源的关键。若是在事务过程当中,咱们mybatis每次都是获取threadlocal中key为AbstractRoutingDataSource的connection,则不会再调用AbstractRoutingDataSource中的getConnection方法切换数据源。springboot
若是想解决这个问题,自定义吧。。。mybatis