PS:欢迎转载,但请注明出处,谢谢配合。
SpringBoot集成Durid,validation-query不执行问题
一、前言
本文章项目基于springboot-2.1.12,使用druid-spring-boot-starter模式集成druid。源码基于 druid-1.1.10 版本,由 druid-spring-boot-starter-1.1.10 传递依赖而来。
二、问题现象
在yml配置文件中,配置了Druid的test-on-borrow参数值为true,同时配置了validation-query语句,但该sql语句对应的数据库表还未创建时,数据库连接池有效性校验居然没有报错。
三、Druid获取连接执行链路梳理
com.alibaba.druid.pool.DruidDataSource.getConnection()
→ getConnection(long)
→ getConnectionDirect(long),
在getConnectionDirect方法中,会判断druid配置参数testOnBorrow是否为true。
1)若为true,则获取数据库连接时,会校验连接的有效性(通过testConnectionInternal方法)。
DruidDataSource.testConnectionInternal
→ DruidAbstractDataSource.testConnectionInternal
→ MySqlValidConnectionChecker.isValidConnection
在isValidConnection方法中,会先判断usePingMethod是否为true。
1)若为true,则会通过ping的方式去判断连接是否有效。此时给druid配置的validation-query根本不会执行。
2)若为false,则会使用给druid配置的validation-query,执行该sql语句判断连接是否有效。
通过的MySqlValidConnectionChecker构造函数可知,当前druid版本的usePingMethod初始为true,所以Druid默认使用的是ping的方式去判断连接是否有效
四、问题原因
如上所述,新版本的Druid,默认使用的是ping的方式去判断连接是否有效,所以根本不会执行validation-query语句。
五、使validation-query执行的方法
MySqlValidConnectionChecker构造函数中,最后一行代码如下:
configFromProperties(System.getProperties());
------------
public void configFromProperties(Properties properties) {
String property = properties.getProperty("druid.mysql.usePingMethod");
if ("true".equals(property)) {
setUsePingMethod(true);
} else if ("false".equals(property)) {
setUsePingMethod(false);
}
}
根据上述源码可知,Druid会根据系统参数中的druid.mysql.usePingMethod值,来控制是否使用ping方式。因此可以通过设置系统参数,将ping方式禁用,则可以使validation-query语句得以执行。(前提是testOnBorrow、testOnReturn、testWhileIdle应该有一个为true)。
java项目启动参数中(jvm参数),设置 -Ddruid.mysql.usePingMethod=false 即可(Eclipse可参考如下方式设置)