springbootmybatisplus多数据源切换sav
背景
最近同事在使用mybatisplus的saveBatch方法时发现报错,提示连接被拒绝,而换成save方法可以正常执行。环境介绍
多数据源masterslave,只从slave读取数据,动态数据源切换是通过sping提供的AbstractRoutingDataSource实现,通过实现mybatis插件,在执行sql时通过sql语句来进行主从库数据源的指定。
springboot2。3。6。RELEASE
mybatisplus3。4。2
mybatis3。5。6
druid1。1。21
mysql8。0。22问题分析与解决根据报错信息,提示操作被拒绝,使用的是slave库的connection去执行插入操作代码逻辑里只有读数据才会连接slave库,也就是selectt语句才会连接slave库操作,这块不会有错,代码上线已久,不会是主从库路由的问题同时发现save操作是正常的,说明问题出在了saveBatch方法上通过断点发现,saveBatch没有执行到mybatis数据源路由的插件逻辑里,而save是可以正常执行路由插件的逻辑的解决方法是,手动在mapperxml里写批量插入的方法源码阅读
查看saveBatch方法源码com。baomidou。mybatisplus。extension。service。IServicesaveBatch(java。util。Collection)
通过传递一个函数参数到下一层执行,这里的insert继续往下走发现com。baomidou。mybatisplus。core。executor。MybatisBatchExecutordoUpdate用于拼接sql与获取connection
进入getConnection方法
org。springframework。jdbc。datasource。DataSourceUtilsdoGetConnection
org。springframework。jdbc。datasource。lookup。AbstractRoutingDataSourcegetConnection()
至此,saveBatch就从determineTargetDataSource中获取到了slave的connection,这里为什么会是slave的connection呢?原来是在批量插入操作之前有一个查询的select操作,导致存放数据源路由的threadLocal中保存的是slave标记。在这里获取完connection后,代码走到数据源路由拦截器中指定master数据源,正确指定master后不生效,这里应该是mybatisplus的一个bug了。
这样,我们还可以通过在saveBatch执行前,强制将数据源指定为MASTER也可以解决这个问题。