使用druid数据库连接池配合presto数据源进行查询时没有问题,数据可以正常查询和展示出来,但是在调用close方法进行关闭连接时报错,报错信息如下:
wyt01-test 2022-07-13 15:14:42,741 [http-nio-8080-exec-3] [ERROR] close statement error - [com.alibaba.druid.util.JdbcUtils.109]
java.sql.SQLFeatureNotSupportedException: Batches not supported
at io.prestosql.jdbc.PrestoStatement.clearBatch(PrestoStatement.java:394)
at com.alibaba.druid.pool.DruidPooledConnection.closePoolableStatement(DruidPooledConnection.java:172)
at com.alibaba.druid.pool.DruidPooledPreparedStatement.close(DruidPooledPreparedStatement.java:201)
at com.alibaba.druid.util.JdbcUtils.close(JdbcUtils.java:98)
at com.alibaba.druid.pool.DruidConnectionHolder.reset(DruidConnectionHolder.java:323)
at com.alibaba.druid.pool.DruidDataSource.recycle(DruidDataSource.java:1949)
at com.alibaba.druid.pool.DruidPooledConnection.recycle(DruidPooledConnection.java:351)
at com.alibaba.druid.pool.DruidPooledConnection.close(DruidPooledConnection.java:288)
at com.haiziwang.bigdata.mokeeper.web.util.PrestoJdbcPoolUtil.close(PrestoJdbcPoolUtil.java:87)
at com.haiziwang.bigdata.mokeeper.web.service.impl.IModelListServiceImpl.notePreview(IModelListServiceImpl.java:1188)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at net.jplugin.core.ctx.impl.DefaultRuleInvocationHandler.invokeWithLog(DefaultRuleInvocationHandler.java:49)
at net.jplugin.core.ctx.impl.DefaultRuleInvocationHandler.invokeWithTx(DefaultRuleInvocationHandler.java:113)
at net.jplugin.core.ctx.impl.DefaultRuleInvocationHandler.lambda$static$2(DefaultRuleInvocationHandler.java:27)
at net.jplugin.common.kits.filter.FilterChain.next(FilterChain.java:32)
at net.jplugin.ext.gtrace.impl.RuleFilter4TraceLog.filter(RuleFilter4TraceLog.java:18)
at net.jplugin.ext.gtrace.impl.RuleFilter4TraceLog.filter(RuleFilter4TraceLog.java:11)
at net.jplugin.common.kits.filter.FilterChain.next(FilterChain.java:32)
at net.jplugin.core.ctx.impl.filter4clazz.RuleCallFilterManagerRuleFilter.filter(RuleCallFilterManagerRuleFilter.java:97)
at net.jplugin.core.ctx.impl.filter4clazz.RuleCallFilterManagerRuleFilter.filter(RuleCallFilterManagerRuleFilter.java:67)
at net.jplugin.common.kits.filter.FilterChain.next(FilterChain.java:32)
at net.jplugin.common.kits.filter.FilterManager.filter(FilterManager.java:42)
at net.jplugin.core.ctx.impl.DefaultRuleInvocationHandler.invoke(DefaultRuleInvocationHandler.java:65)
at net.jplugin.core.ctx.impl.RuleInterceptor.invoke(RuleInterceptor.java:134)
at com.sun.proxy.$Proxy17.notePreview(Unknown Source)
at com.haiziwang.bigdata.mokeeper.web.controller.ModelListController.notePreview(ModelListController.java:330)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at net.jplugin.core.ctx.impl.DefaultRuleInvocationHandler.invokeWithLog(DefaultRuleInvocationHandler.java:49)
at net.jplugin.core.ctx.impl.DefaultRuleInvocationHandler.invokeWithTx(DefaultRuleInvocationHandler.java:113)
at net.jplugin.core.ctx.impl.DefaultRuleInvocationHandler.lambda$static$2(DefaultRuleInvocationHandler.java:27)
at net.jplugin.common.kits.filter.FilterChain.next(FilterChain.java:32)
at net.jplugin.ext.gtrace.impl.RuleFilter4TraceLog.filter(RuleFilter4TraceLog.java:18)
at net.jplugin.ext.gtrace.impl.RuleFilter4TraceLog.filter(RuleFilter4TraceLog.java:11)
at net.jplugin.common.kits.filter.FilterChain.next(FilterChain.java:32)
at com.haiziwang.platform.auth.BaseUserAuthInceptor.filterRuleMethod(BaseUserAuthInceptor.java:120)
at net.jplugin.core.ctx.api.AbstractRuleMethodInterceptor.filter(AbstractRuleMethodInterceptor.java:25)
at net.jplugin.core.ctx.impl.filter4clazz.RuleCallFilterManagerRuleFilter$ClassOwnedFilter.filter(RuleCallFilterManagerRuleFilter.java:199)
at net.jplugin.core.ctx.impl.filter4clazz.RuleCallFilterManagerRuleFilter$ClassOwnedFilter.filter(RuleCallFilterManagerRuleFilter.java:186)
at net.jplugin.common.kits.filter.FilterChain.next(FilterChain.java:32)
at com.haiziwang.platform.auth.BaseSsoAuthInterceptor.filterRuleMethod(BaseSsoAuthInterceptor.java:127)
at net.jplugin.core.ctx.api.AbstractRuleMethodInterceptor.filter(AbstractRuleMethodInterceptor.java:25)
at net.jplugin.core.ctx.impl.filter4clazz.RuleCallFilterManagerRuleFilter$ClassOwnedFilter.filter(RuleCallFilterManagerRuleFilter.java:199)
at net.jplugin.core.ctx.impl.filter4clazz.RuleCallFilterManagerRuleFilter$ClassOwnedFilter.filter(RuleCallFilterManagerRuleFilter.java:186)
at net.jplugin.common.kits.filter.FilterChain.next(FilterChain.java:32)
at com.haiziwang.platform.esf.server.interceptor.AppAuthInterceptor.filterRuleMethod(AppAuthInterceptor.java:38)
at net.jplugin.core.ctx.api.AbstractRuleMethodInterceptor.filter(AbstractRuleMethodInterceptor.java:25)
at net.jplugin.core.ctx.impl.filter4clazz.RuleCallFilterManagerRuleFilter$ClassOwnedFilter.filter(RuleCallFilterManagerRuleFilter.java:199)
at net.jplugin.core.ctx.impl.filter4clazz.RuleCallFilterManagerRuleFilter$ClassOwnedFilter.filter(RuleCallFilterManagerRuleFilter.java:186)
at net.jplugin.common.kits.filter.FilterChain.next(FilterChain.java:32)
at com.haiziwang.platform.kflow.interceptor.FlowControlInterceptor.filterRuleMethod(FlowControlInterceptor.java:56)
at net.jplugin.core.ctx.api.AbstractRuleMethodInterceptor.filter(AbstractRuleMethodInterceptor.java:25)
at net.jplugin.core.ctx.impl.filter4clazz.RuleCallFilterManagerRuleFilter$ClassOwnedFilter.filter(RuleCallFilterManagerRuleFilter.java:199)
at net.jplugin.core.ctx.impl.filter4clazz.RuleCallFilterManagerRuleFilter$ClassOwnedFilter.filter(RuleCallFilterManagerRuleFilter.java:186)
at net.jplugin.common.kits.filter.FilterChain.next(FilterChain.java:32)
at net.jplugin.common.kits.filter.FilterManager.filter(FilterManager.java:42)
at net.jplugin.core.ctx.impl.filter4clazz.RuleCallFilterManagerRuleFilter.filter(RuleCallFilterManagerRuleFilter.java:99)
at net.jplugin.core.ctx.impl.filter4clazz.RuleCallFilterManagerRuleFilter.filter(RuleCallFilterManagerRuleFilter.java:67)
at net.jplugin.common.kits.filter.FilterChain.next(FilterChain.java:32)
at net.jplugin.common.kits.filter.FilterManager.filter(FilterManager.java:42)
at net.jplugin.core.ctx.impl.DefaultRuleInvocationHandler.invoke(DefaultRuleInvocationHandler.java:65)
at net.jplugin.core.ctx.api.RuleProxyHelper.invokeWithRule(RuleProxyHelper.java:27)
at net.jplugin.ext.webasic.impl.web.webex.WebExController$1.run(WebExController.java:87)
at net.jplugin.ext.webasic.impl.filter.MethodFilterManager.executeWithFilter(MethodFilterManager.java:31)
at net.jplugin.ext.webasic.impl.web.webex.WebExController.dohttp(WebExController.java:85)
at net.jplugin.ext.webasic.impl.web.webex.WebExControllerSet.dohttp(WebExControllerSet.java:47)
at net.jplugin.ext.webasic.impl.WebDriver.doHttpAcure(WebDriver.java:110)
at net.jplugin.ext.webasic.impl.WebDriver.lambda$new$2(WebDriver.java:45)
at net.jplugin.common.kits.filter.FilterChain.next(FilterChain.java:32)
at net.jplugin.extension.reqrecoder.impl.ReqLogFilter.filter(ReqLogFilter.java:47)
at net.jplugin.extension.reqrecoder.impl.ReqLogFilter.filter(ReqLogFilter.java:13)
at net.jplugin.common.kits.filter.FilterChain.next(FilterChain.java:32)
at net.jplugin.ext.gtrace.impl.HttpFilter4TraceLog.filter(HttpFilter4TraceLog.java:28)
at net.jplugin.ext.gtrace.impl.HttpFilter4TraceLog.filter(HttpFilter4TraceLog.java:12)
at net.jplugin.common.kits.filter.FilterChain.next(FilterChain.java:32)
at net.jplugin.common.kits.filter.FilterManager.filter(FilterManager.java:42)
at net.jplugin.ext.webasic.impl.WebDriver.dohttp(WebDriver.java:87)
at net.jplugin.ext.webasic.impl.PluginServlet.dohttp(PluginServlet.java:64)
at net.jplugin.ext.webasic.impl.PluginServlet.doPost(PluginServlet.java:53)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:652)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:733)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at com.thetransactioncompany.cors.CORSFilter.doFilter(CORSFilter.java:209)
at com.thetransactioncompany.cors.CORSFilter.doFilter(CORSFilter.java:244)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:199)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:544)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:143)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81)
at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:698)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:353)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:616)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:831)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1629)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:748)
因为报错是在close方法中,于是查看close报错的方法栈,可以看到如下的流程信息:
即connection关闭时会调用数据源的recycle方法回收connection连接到连接池, 我们再深入看一下:
可以看到再回收连接时会重设连接的一些信息,我们接着深入看一下:
可以看到重置connection连接时,会关闭所有的statement会话,因为我们用的是PrepareStatement,所以到DruidPooledPreparedStatement查看下关闭的具体方法:
可以看到最druid关闭connection连接中的preparestatement时会调用presto jdbc驱动中的clearBatch方法,我们再到presto驱动中看一下该方法的实现:
可以看到presto对该方法本身就不支持,而且也就是报错的根本原因。
总结:druid线程池中连接关闭时,druid会同时关闭statement,而我们使用的prestatement,它在druid中会去调用jdbc驱动的clearBatch方法,这个方法在presto中并没有被实现,因此会报“Batches not supported”问题。
1)重写druid中prestatement的关闭方法
2)重写presto驱动中的clearBatch方法。
3)替换prestatement为常规的statement(我使用的就是这种,比较前两种改动太大)。
使用druid连接时,只需要手动关闭connection连接即可,其内部会帮助我们关闭statement和resultset。因为在阅读connection关闭源码时,我们看到了如下一段代码:
for (Object item : statementTrace.toArray()) {
Statement stmt = (Statement) item;
JdbcUtils.close(stmt);
}
即在connection关闭的过程中,会将自己相关的statement也关闭掉,同理resultset也会再statement的关闭中被关闭,因此使用druid线程池关闭时只需要关闭connection即可。