Spring的JdbcTemplate使用,是否还需要手工或者aop指定关闭conn连接( 使用JdbcTemplate是否需要关闭连接)...

Spring的JdbcTemplate在执行数据库操作时会自动管理连接,包括打开和关闭。当使用PreparedStatementCreator和PreparedStatementCallback时,即使发生异常,JdbcTemplate也会确保在适当的时候释放并关闭连接。在finally块中,JdbcTemplate关闭了PreparedStatement并释放了DataSource提供的Connection,从而避免连接池死锁。

JdbcTemplate类使用DataSource得到一个数据库连接。然后,他调用StatementCreator实例创建要执行的语句。下一步,他调用StatementCallBack完成。
一旦StatementCallBack返回结果,JdbcTemplate类完成所有必要清理工作关闭连接。如果StatementCreator或StatementCallBack抛出异常,JdbcTemplate类会捕获他们,并转换为Spring数据访问异常。




看一个JdbcTemplate里面的比较核心的一个方法:

  1. //-------------------------------------------------------------------------
  2. // Methods dealing with prepared statements
  3. //-------------------------------------------------------------------------
  4. publicObject execute(PreparedStatementCreator psc, PreparedStatementCallback action)
  5. throwsDataAccessException {
  6. Assert.notNull(psc,"PreparedStatementCreator must not be null");
  7. Assert.notNull(action,"Callback object must not be null");
  8. if(logger.isDebugEnabled()) {
  9. String sql = getSql(psc);
  10. logger.debug("Executing prepared SQL statement"+ (sql !=null?" ["+ sql +"]":""));
  11. }
  12. Connection con = DataSourceUtils.getConnection(getDataSource());
  13. PreparedStatement ps =null;
  14. try{
  15. Connection conToUse = con;
  16. if(this.nativeJdbcExtractor !=null&&
  17. this.nativeJdbcExtractor.isNativeConnectionNecessaryForNativePreparedStatements()) {
  18. conToUse =this.nativeJdbcExtractor.getNativeConnection(con);
  19. }
  20. ps = psc.createPreparedStatement(conToUse);
  21. applyStatementSettings(ps);
  22. PreparedStatement psToUse = ps;
  23. if(this.nativeJdbcExtractor !=null) {
  24. psToUse =this.nativeJdbcExtractor.getNativePreparedStatement(ps);
  25. }
  26. Object result = action.doInPreparedStatement(psToUse);
  27. handleWarnings(ps);
  28. returnresult;
  29. }
  30. catch(SQLException ex) {
  31. // Release Connection early, to avoid potential connection pool deadlock
  32. // in the case when the exception translator hasn't been initialized yet.
  33. if(pscinstanceofParameterDisposer) {
  34. ((ParameterDisposer) psc).cleanupParameters();
  35. }
  36. String sql = getSql(psc);
  37. psc =null;
  38. JdbcUtils.closeStatement(ps);
  39. ps =null;
  40. DataSourceUtils.releaseConnection(con, getDataSource());
  41. con =null;
  42. throwgetExceptionTranslator().translate("PreparedStatementCallback", sql, ex);
  43. }
  44. finally{
  45. if(pscinstanceofParameterDisposer) {
  46. ((ParameterDisposer) psc).cleanupParameters();
  47. }
  48. JdbcUtils.closeStatement(ps);
  49. DataSourceUtils.releaseConnection(con, getDataSource());
  50. }
  51. }

显然,我们在finally里面看到了关闭调用,在看看这个关闭调用方法内部:
  1. /**
  2. * Close the given Connection, obtained from the given DataSource,
  3. * if it is not managed externally (that is, not bound to the thread).
  4. * @param con the Connection to close if necessary
  5. * (if this is <code>null</code>, the call will be ignored)
  6. * @param dataSource the DataSource that the Connection was obtained from
  7. * (may be <code>null</code>)
  8. * @see #getConnection
  9. */
  10. publicstaticvoidreleaseConnection(Connection con, DataSource dataSource) {
  11. try{
  12. doReleaseConnection(con, dataSource);
  13. }
  14. catch(SQLException ex) {
  15. logger.debug("Could not close JDBC Connection", ex);
  16. }
  17. catch(Throwable ex) {
  18. logger.debug("Unexpected exception on closing JDBC Connection", ex);
  19. }
  20. }
  21. /**
  22. * Actually close the given Connection, obtained from the given DataSource.
  23. * Same as {@link #releaseConnection}, but throwing the original SQLException.
  24. * <p>Directly accessed by {@link TransactionAwareDataSourceProxy}.
  25. * @param con the Connection to close if necessary
  26. * (if this is <code>null</code>, the call will be ignored)
  27. * @param dataSource the DataSource that the Connection was obtained from
  28. * (may be <code>null</code>)
  29. * @throws SQLException if thrown by JDBC methods
  30. * @see #doGetConnection
  31. */
  32. publicstaticvoiddoReleaseConnection(Connection con, DataSource dataSource)throwsSQLException {
  33. if(con ==null) {
  34. return;
  35. }
  36. if(dataSource !=null) {
  37. ConnectionHolder conHolder = (ConnectionHolder) TransactionSynchronizationManager.getResource(dataSource);
  38. if(conHolder !=null&& connectionEquals(conHolder, con)) {
  39. // It's the transactional Connection: Don't close it.
  40. conHolder.released();
  41. return;
  42. }
  43. }
  44. // Leave the Connection open only if the DataSource is our
  45. // special SmartDataSoruce and it wants the Connection left open.
  46. if(!(dataSourceinstanceofSmartDataSource) || ((SmartDataSource) dataSource).shouldClose(con)) {
  47. logger.debug("Returning JDBC Connection to DataSource");
  48. con.close();
  49. }
  50. }

主要下面这几行代码:
  1. // Leave the Connection open only if the DataSource is our
  2. // special SmartDataSoruce and it wants the Connection left open.
  3. if(!(dataSourceinstanceofSmartDataSource) || ((SmartDataSource) dataSource).shouldClose(con)) {
  4. logger.debug("Returning JDBC Connection to DataSource");
  5. con.close();
  6. }

哦,可以看到大部分情况下是自动关闭,除非你使用的SmartDataSource,且SmartDataSource指定了允许关闭。


有些时候,你引入了JdbcTemplate或者DaoSupport,但是有时还需要自己额外的拿到conn进行操作,如下:
jdbcTemplate.getDataSource().getConnection()
那么,你应该就需要关闭连接了

clickhouse数据库jdbc0.9.0版本报错org.springframework.jdbc.UncategorizedSQLException: PreparedStatementCallback; uncategorized SQLException for SQL [INSERT INTO ads_test_licheng.dwd_sop_sale_order_test VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) ]; SQL state [HY000]; error code [0]; -2110258699 at org.springframework.jdbc.core.JdbcTemplate.translateException(JdbcTemplate.java:1549) at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:677) at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:701) at org.springframework.jdbc.core.JdbcTemplate.batchUpdate(JdbcTemplate.java:1047) at com.licheng.erpToWms.utils.ClickHouseUtils.Insert(ClickHouseUtils.java:47) at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) at java.base/java.lang.reflect.Method.invoke(Method.java:580) at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:351) at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:196) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:765) at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:137) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184) at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:765) at com.baomidou.dynamic.datasource.aop.DynamicDataSourceAnnotationInterceptor.invoke(DynamicDataSourceAnnotationInterceptor.java:57) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184) at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:765) at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:717) at com.licheng.erpToWms.utils.ClickHouseUtils$$SpringCGLIB$$0.Insert(<generated>) at com.licheng.erpToWms.utils.AssignUtils.batchInsert(AssignUtils.java:24) at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) at java.base/java.lang.reflect.Method.invoke(Method.java:580) at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:351) at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:196) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:765) at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:137) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184) at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:765) at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:717) at com.licheng.erpToWms.utils.AssignUtils$$SpringCGLIB$$0.batchInsert(<generated>) at com.licheng.erpToWms.service.impl.SyncSaleOrderServiceImpl.lambda$syncSaleOrder$0(SyncSaleOrderServiceImpl.java:259) at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:572) at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:317) at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144) at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642) at java.base/java.lang.Thread.run(Thread.java:1583) Caused by: java.sql.SQLException: -2110258699 at com.clickhouse.jdbc.internal.ExceptionUtils.toSqlState(ExceptionUtils.java:69) at com.clickhouse.jdbc.internal.ExceptionUtils.toSqlState(ExceptionUtils.java:42) at com.clickhouse.jdbc.StatementImpl.executeUpdateImpl(StatementImpl.java:191) at com.clickhouse.jdbc.PreparedStatementImpl.executeInsertBatch(PreparedStatementImpl.java:331) at com.clickhouse.jdbc.PreparedStatementImpl.executeBatch(PreparedStatementImpl.java:297) at com.alibaba.druid.filter.FilterChainImpl.statement_executeBatch(FilterChainImpl.java:3101) at com.alibaba.druid.filter.FilterAdapter.statement_executeBatch(FilterAdapter.java:2506) at com.alibaba.druid.filter.FilterEventAdapter.statement_executeBatch(FilterEventAdapter.java:273) at com.alibaba.druid.filter.FilterChainImpl.statement_executeBatch(FilterChainImpl.java:3099) at com.alibaba.druid.proxy.jdbc.StatementProxyImpl.executeBatch(StatementProxyImpl.java:198) at com.alibaba.druid.pool.DruidPooledPreparedStatement.executeBatch(DruidPooledPreparedStatement.java:551) at org.springframework.jdbc.core.JdbcTemplate.lambda$getPreparedStatementCallback$6(JdbcTemplate.java:1609) at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:658) ... 35 more Caused by: com.clickhouse.client.api.ClientException: -2110258699 at com.clickhouse.client.api.internal.HttpAPIClientHelper.executeRequest(HttpAPIClientHelper.java:442) at com.clickhouse.client.api.Client.lambda$query$10(Client.java:1723) at com.clickhouse.client.api.Client.runAsyncOperation(Client.java:2156) at com.clickhouse.client.api.Client.query(Client.java:1766) at com.clickhouse.client.api.Client.query(Client.java:1667) at com.clickhouse.jdbc.StatementImpl.executeUpdateImpl(StatementImpl.java:184) ... 45 more Caused by: java.lang.NegativeArraySizeException: -2110258699 at java.base/java.lang.String.encodeUTF8_UTF16(String.java:1326) at java.base/java.lang.String.encodeUTF8(String.java:1299) at java.base/java.lang.String.encode(String.java:867) at java.base/java.lang.String.getBytes(String.java:1818) at com.clickhouse.client.api.Client.lambda$query$9(Client.java:1724) at com.clickhouse.client.internal.apache.hc.core5.http.io.entity.EntityTemplate.writeTo(EntityTemplate.java:82) at com.clickhouse.client.internal.apache.hc.core5.http.impl.io.DefaultBHttpClientConnection.sendRequestEntity(DefaultBHttpClientConnection.java:253) at com.clickhouse.client.internal.apache.hc.core5.http.impl.io.HttpRequestExecutor.execute(HttpRequestExecutor.java:141) at com.clickhouse.client.internal.apache.hc.core5.http.impl.io.HttpRequestExecutor.execute(HttpRequestExecutor.java:218) at com.clickhouse.client.internal.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager$InternalConnectionEndpoint.execute(PoolingHttpClientConnectionManager.java:712) at com.clickhouse.client.internal.apache.hc.client5.http.impl.classic.InternalExecRuntime.execute(InternalExecRuntime.java:216) at com.clickhouse.client.internal.apache.hc.client5.http.impl.classic.MainClientExec.execute(MainClientExec.java:116) at com.clickhouse.client.internal.apache.hc.client5.http.impl.classic.ExecChainElement.execute(ExecChainElement.java:51) at com.clickhouse.client.internal.apache.hc.client5.http.impl.classic.ConnectExec.execute(ConnectExec.java:188) at com.clickhouse.client.internal.apache.hc.client5.http.impl.classic.ExecChainElement.execute(ExecChainElement.java:51) at com.clickhouse.client.internal.apache.hc.client5.http.impl.classic.ProtocolExec.execute(ProtocolExec.java:192) at com.clickhouse.client.internal.apache.hc.client5.http.impl.classic.ExecChainElement.execute(ExecChainElement.java:51) at com.clickhouse.client.internal.apache.hc.client5.http.impl.classic.HttpRequestRetryExec.execute(HttpRequestRetryExec.java:96) at com.clickhouse.client.internal.apache.hc.client5.http.impl.classic.ExecChainElement.execute(ExecChainElement.java:51) at com.clickhouse.client.internal.apache.hc.client5.http.impl.classic.ContentCompressionExec.execute(ContentCompressionExec.java:152) at com.clickhouse.client.internal.apache.hc.client5.http.impl.classic.ExecChainElement.execute(ExecChainElement.java:51) at com.clickhouse.client.internal.apache.hc.client5.http.impl.classic.RedirectExec.execute(RedirectExec.java:115) at com.clickhouse.client.internal.apache.hc.client5.http.impl.classic.ExecChainElement.execute(ExecChainElement.java:51) at com.clickhouse.client.internal.apache.hc.client5.http.impl.classic.InternalHttpClient.doExecute(InternalHttpClient.java:170) at com.clickhouse.client.internal.apache.hc.client5.http.impl.classic.CloseableHttpClient.execute(CloseableHttpClient.java:87) at com.clickhouse.client.internal.apache.hc.client5.http.impl.classic.CloseableHttpClient.execute(CloseableHttpClient.java:55) at com.clickhouse.client.internal.apache.hc.client5.http.classic.HttpClient.executeOpen(HttpClient.java:183) at com.clickhouse.client.api.internal.HttpAPIClientHelper.executeRequest(HttpAPIClientHelper.java:415) ... 50 more MyException(errorCode=DEFAULT_ERROR) at com.licheng.erpToWms.utils.ClickHouseUtils.Insert(ClickHouseUtils.java:66) at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) at java.base/java.lang.reflect.Method.invoke(Method.java:580) at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:351) at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:196) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:765) at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:137) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184) at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:765) at com.baomidou.dynamic.datasource.aop.DynamicDataSourceAnnotationInterceptor.invoke(DynamicDataSourceAnnotationInterceptor.java:57) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184) at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:765) at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:717) at com.licheng.erpToWms.utils.ClickHouseUtils$$SpringCGLIB$$0.Insert(<generated>) at com.licheng.erpToWms.utils.AssignUtils.batchInsert(AssignUtils.java:24) at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) at java.base/java.lang.reflect.Method.invoke(Method.java:580) at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:351) at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:196) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:765) at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:137) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184) at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:765) at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:717) at com.licheng.erpToWms.utils.AssignUtils$$SpringCGLIB$$0.batchInsert(<generated>) at com.licheng.erpToWms.service.impl.SyncSaleOrderServiceImpl.lambda$syncSaleOrder$0(SyncSaleOrderServiceImpl.java:259) at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:572) at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:317) at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144) at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642) at java.base/java.lang.Thread.run(Thread.java:1583)
最新发布
06-26
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值