求助!Spring下使用JNDI数据源时JDBCTemplate数据库连接关闭的问题!

时间:2021-06-01 23:51:17
最近在接手一个项目的时候,偶尔出现一个问题,JDBCTemplate用得好好的,突然后台狂报错,其中一个报错内容如下:
org.springframework.jdbc.UncategorizedSQLException: PreparedStatementCallback; uncategorized SQLException for SQL [select CNTR_EF_ID from ship_bill where bill_no = ?]; SQL state [null]; error code [17008]; 关闭的连接; nested exception is java.sql.SQLException: 关闭的连接
        at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:83)
        at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:80)
        at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:80)
        at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:602)
        at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:636)
        at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:665)
        at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:673)
        at org.springframework.jdbc.core.JdbcTemplate.queryForObject(JdbcTemplate.java:728)
        at org.springframework.jdbc.core.JdbcTemplate.queryForObject(JdbcTemplate.java:744)
        at net.huadong.eservices.edi.action.DeliorAction.generateDeliorIFV(DeliorAction.java:180)
        at sun.reflect.GeneratedMethodAccessor685.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:606)
        at com.webbuilder.utils.SysUtil.executeMethod(SysUtil.java:55)
        at com.webbuilder.controls.Method.descript(Method.java:11)
        at com.webbuilder.controls.Control.create(Control.java:50)
        at com.webbuilder.common.Parser.createControl(Parser.java:546)
        at com.webbuilder.common.Parser.parseElements(Parser.java:462)
        at com.webbuilder.common.Parser.parseElements(Parser.java:465)
        at com.webbuilder.common.Parser.parse(Parser.java:165)
        at com.webbuilder.common.Main.doGet(Main.java:193)
        at com.webbuilder.common.Main.doPost(Main.java:266)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:643)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:723)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
        at org.jboss.resteasy.plugins.server.servlet.FilterDispatcher.doFilter(FilterDispatcher.java:63)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
        at net.huadong.port.lsmp.filter.LoginFilter.doFilter(LoginFilter.java:101)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
        at net.bull.javamelody.MonitoringFilter.doFilter(MonitoringFilter.java:206)
        at net.bull.javamelody.MonitoringFilter.doFilter(MonitoringFilter.java:179)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
        at net.huadong.pass.core.platform.webService.WebServiceFilter.doFilter(WebServiceFilter.java:52)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293)
        at org.apache.coyote.http11.Http11NioProcessor.process(Http11NioProcessor.java:891)
        at org.apache.coyote.http11.Http11NioProtocol$Http11ConnectionHandler.process(Http11NioProtocol.java:750)
        at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:2282)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
        at java.lang.Thread.run(Thread.java:744)

JNDI配置如下:
<Resource name="jdbc/shjjhy" 
    auth="Container" type="javax.sql.DataSource" 
driverClassName="oracle.jdbc.driver.OracleDriver" 
url="jdbc:oracle:thin:@***" 
username="***" 
password="***" 
testOnBorrow="true"
testWhileIdle="true" 
testOnReturn="true"
validationQuery="select 1 from dual"
minEvictableIdleTimeMillis="10000"
timeBetweenEvictionRunsMillis="10000"
maxActive="500" 
maxIdle="50" 
maxWait="1000"  removeAbandoned="true" removeAbandonedTimeout="60" logAbandoned="true"   initialSize="5" />


Spring的配置如下:
<bean id="dataSourceJNDI" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName">
<value>java:comp/env/jdbc/shjjhy</value>
</property>
</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"
abstract="false" lazy-init="false">
<property name="dataSource">
<ref bean="dataSourceJNDI" />
</property>
</bean>

JDBCTemplate默认是使用的单例模式,在系统中我们是这样获取JDBCTemplate的:

WebApplicationContext ctx = (WebApplicationContext) request
.getAttribute("WebApplicationContext");
JdbcTemplate jt = (JdbcTemplate) ctx.getBean("jdbcTemplate");


基本上是所有只要使用JDBCTemplate进行数据操作的地方都会报错,我在后台监控也看到了,数据连接池最高的时候也就20个连接,而且关键就是在系统运行一段时间后才会出这个问题,时间不确定,有时候一两个星期出现,有时候一天出现两三次,每次都只能通过重启Tomcat来解决。

我想了好久,觉得最大的可能性是,JDBCTemplate在某个地方被强制关闭了,但是JDBCTemplate的Connection关闭我记得是自己处理的啊,所以我也不知道到哪里去找错误的根源,所以来请教各路大神!!!看各位是否遇到过这种情况;

我总结下:
1、一般都是系统在运行一段时间后才会报错,而且只要是使用JDBCTemplate的地方就会报错,如果是直接获取Connection来调用是不会报错的;
2、连接数最高不超过20,远远没有达到连接池的限制,如图:
求助!Spring下使用JNDI数据源时JDBCTemplate数据库连接关闭的问题!
3、每次都只能通过重启服务器解决此问题,是否有好的解决方案或者思路?

21 个解决方案

#1


这种现象一般是使用了关闭的Connection,
你仔细检查下代码是不是哪个地方使用了关闭的Connection操作了?

#2


引用 1 楼 luntanrenhaoduo 的回复:
这种现象一般是使用了关闭的Connection,
你仔细检查下代码是不是哪个地方使用了关闭的Connection操作了?


感谢您的回复,就是这一点我很疑惑,JDBCTemplate中是自己封装了关闭数据库的连接,如何能让程序员显性的把JDBCTemplate中使用的Connection关闭呢?

#3


因为你是接手的项目,而不是你自己写的。
有些人在操作SQL时喜欢在程序里自己弄一个Connection进行操作.
而这个Connection是通过JDBCTemplate get到的,又进行了违规的操作.

至于为啥这么写...我觉得你应该去问问给你项目的那个人.

#4


引用 3 楼 luntanrenhaoduo 的回复:
因为你是接手的项目,而不是你自己写的。
有些人在操作SQL时喜欢在程序里自己弄一个Connection进行操作.
而这个Connection是通过JDBCTemplate get到的,又进行了违规的操作.

至于为啥这么写...我觉得你应该去问问给你项目的那个人.


大神,我在我的项目中搜索到了一段代码,麻烦您看下,是不是这样的就会出现这样的问题?


WebApplicationContext ctx = (WebApplicationContext) request.getAttribute("WebApplicationContext");
JdbcTemplate jt = (JdbcTemplate) ctx.getBean("jdbcTemplate");
Connection con = null;
try{
con  = jt.getDataSource().getConnection();
con.setAutoCommit(false);
/**
 * 业务操作
 */
con.setAutoCommit(true);
}catch(Exception e){
e.printStackTrace();
try {
con.setAutoCommit(true);
} catch (SQLException e1) {
e1.printStackTrace();
}
}finally{
DbUtil.closeConnection(con, true);
}

然后上面的DbUtil.closeConnection(con, true);的方法如下:

public static boolean closeConnection(Connection connection,
boolean isExcept) {
/* 331 */boolean status = true;
try {
/* 333 */if ((connection != null) && (!connection.isClosed())) {
/* 334 */if (!connection.getAutoCommit())
try {
/* 336 */if (isExcept)
/* 337 */connection.rollback();
else
/* 339 */connection.commit();
} catch (Exception e) {
/* 341 */status = false;
/* 342 */if (!isExcept)
/* 343 */connection.rollback();
} finally {
/* 345 */connection.setAutoCommit(true);
}
/* 347 */connection.close();
/* 348 */connection = null;
}
} catch (Exception e) {
/* 351 */status = false;
}
/* 353 */return status;
}


再次感谢大神的指导!

#5


你找下 select CNTR_EF_ID from ship_bill where bill_no = ? 这个sql用的会话对象是怎么操作的,不行把这段代码删掉,测试下,会不会报错还.

#6


不需要显示关闭连接的

#7


一个可能的原因是,某个地方的连接没有关闭,导致连接被消耗光了。

#8


引用 5 楼 luntanrenhaoduo 的回复:
你找下 select CNTR_EF_ID from ship_bill where bill_no = ? 这个sql用的会话对象是怎么操作的,不行把这段代码删掉,测试下,会不会报错还.


他这个不仅是这一个地方报错,是有很多地方都报错,我只是把其中一个错误贴出来而已,而且都是一些不相关的业务或者代码都只要用到了JDBCTemplate就会报错;
其中我拿出来的这个报错的地方是这样使用的:


String emptyBillSql = "select CNTR_EF_ID from ship_bill where bill_no = ?";
try {
WebApplicationContext ctx = (WebApplicationContext) request
.getAttribute("WebApplicationContext");
JdbcTemplate jt = (JdbcTemplate) ctx.getBean("jdbcTemplate");
for (String bill : bills) {
if (!StringUtil.isEmpty(bill)) {
bi = bill.split("-");
String billEFId = "F";
try {
billEFId = jt.queryForObject(emptyBillSql, new Object[]{bi[0]}, String.class);
} catch (Exception e) {
e.printStackTrace();
billEFId = "F";
}
// 以下代码省略


有的地方使用的是jt.queryForList 也一样的报错;就是那种突然就出现了,然后后台疯狂报错,全都是关闭的连接这样的错误。所以我也是怀疑是不是因为单例模式的影响,在某个地方把JDBCTemplate的连接关闭了,其他地方只要引用JDBCTemplate就都报错了。
但是我也不知道是什么样的代码能做到把JDBCTemplate的连接关闭而且让Spring不会新获取连接。

#9


引用 6 楼 okafor2011 的回复:
不需要显示关闭连接的


我也查了很多资料是不应该显示的关闭连接;所以我也不确定下面这段代码是不是有问题,也不轻视是否会造成我前面说的那种情况出现:


WebApplicationContext ctx = (WebApplicationContext) request.getAttribute("WebApplicationContext");
JdbcTemplate jt = (JdbcTemplate) ctx.getBean("jdbcTemplate");
Connection con = null;
try{
con  = jt.getDataSource().getConnection();
con.setAutoCommit(false);
/**
 * 业务操作
 */
con.setAutoCommit(true);
}catch(Exception e){
e.printStackTrace();
try {
con.setAutoCommit(true);
} catch (SQLException e1) {
e1.printStackTrace();
}
}finally{
DbUtil.closeConnection(con, true);
}

#10


引用 7 楼 Q80470101 的回复:
一个可能的原因是,某个地方的连接没有关闭,导致连接被消耗光了。


一开始我也以为是这个原因,但是我的连接池设置了500的连接,这是很久以前以为是连接数的问题,所以设了这么大,但是我上面也给出了我们监控系统的图表,今天的最大连接数才19,但是今天就出现两次这样的问题, 我只能重启服务器才能解决。

#11


引用 10 楼 yzjdt 的回复:
Quote: 引用 7 楼 Q80470101 的回复:

一个可能的原因是,某个地方的连接没有关闭,导致连接被消耗光了。


一开始我也以为是这个原因,但是我的连接池设置了500的连接,这是很久以前以为是连接数的问题,所以设了这么大,但是我上面也给出了我们监控系统的图表,今天的最大连接数才19,但是今天就出现两次这样的问题, 我只能重启服务器才能解决。


我建议你去检查下所有jdbc的代码(你们代码中所有的jdbc,不只是JDBCTemplate),你的现象和这个猜测很吻合。
ps: ctrl+shift+g 快捷键可以查看到所有引用。

#12


JdbcTemplate是spring封装的快速操作数据库的一套API,你可以点击进去看下源代码(这里就不提供了,没找到例子,这个东西已经被我们摒弃很多年了),肯定是不需要自己关闭的,而且后面看了下,WebApplicationContext ctx = (WebApplicationContext) request.getAttribute("WebApplicationContext");
JdbcTemplate jt = (JdbcTemplate) ctx.getBean("jdbcTemplate");
Connection con = null;
try{
    con  = jt.getDataSource().getConnection();
    con.setAutoCommit(false);
    /**
     * 业务操作
     */
    con.setAutoCommit(true);
}catch(Exception e){
    e.printStackTrace();
    try {
        con.setAutoCommit(true);
    } catch (SQLException e1) {
        e1.printStackTrace();
    }
}finally{
    DbUtil.closeConnection(con, true);
}
这块好像是要对事物做控制,不知道有AOP这个东西么,这块是线程安全的不,你的问题很可能是线程不安全导致

#13


引用 11 楼 Q80470101 的回复:
Quote: 引用 10 楼 yzjdt 的回复:

Quote: 引用 7 楼 Q80470101 的回复:

一个可能的原因是,某个地方的连接没有关闭,导致连接被消耗光了。


一开始我也以为是这个原因,但是我的连接池设置了500的连接,这是很久以前以为是连接数的问题,所以设了这么大,但是我上面也给出了我们监控系统的图表,今天的最大连接数才19,但是今天就出现两次这样的问题, 我只能重启服务器才能解决。


我建议你去检查下所有jdbc的代码(你们代码中所有的jdbc,不只是JDBCTemplate),你的现象和这个猜测很吻合。
ps: ctrl+shift+g 快捷键可以查看到所有引用。


也就是说如果jdbc的Connection是从JdbcTemplate里面取出来的话,再关闭是很有可能出现这种问题的?

#14


引用 12 楼 xiaohuashenshou 的回复:
JdbcTemplate是spring封装的快速操作数据库的一套API,你可以点击进去看下源代码(这里就不提供了,没找到例子,这个东西已经被我们摒弃很多年了),肯定是不需要自己关闭的,而且后面看了下,WebApplicationContext ctx = (WebApplicationContext) request.getAttribute("WebApplicationContext");
JdbcTemplate jt = (JdbcTemplate) ctx.getBean("jdbcTemplate");
Connection con = null;
try{
    con  = jt.getDataSource().getConnection();
    con.setAutoCommit(false);
    /**
     * 业务操作
     */
    con.setAutoCommit(true);
}catch(Exception e){
    e.printStackTrace();
    try {
        con.setAutoCommit(true);
    } catch (SQLException e1) {
        e1.printStackTrace();
    }
}finally{
    DbUtil.closeConnection(con, true);
}
这块好像是要对事物做控制,不知道有AOP这个东西么,这块是线程安全的不,你的问题很可能是线程不安全导致


当时做这个项目的时候,并没有完全按照Spring的方式来做,就算JDBCTemplate老一点也没什么大问题,但问题就是,他们很多都是把JdbcTemplate转为原始的Connection后再操作,导致这个项目里面最少用了三种JDBC的操作,AOP更加没用上。

然后您说的关于线程的,这个方法并没有加任何synchronized的关键字来控制线程安全,然后我看了一下这段代码,然后也是我的疑惑所在,JdbcTemplate虽然是单例模式,但是不应该是每次我从Spring容器里面取一个JdbcTemplate出来的时候,应该就会向连接池要一个新连接对吧?如果是这样,就算这段代码里面我手动关闭了,应该也不会造成其他地方只要一调用JdbcTemplate就会报错吧?这样的话岂不是JDBCTemplate里面永远只有一个有效的连接?所有地方调用JdbcTemplate都是使用同一个Connection来操作的?

#15


你可以先把手动获取连接的代码先屏蔽,然后观察一段时间看看。

#16


没办法回答你那么详细来了,呵呵,这个东西N多年不用了,里面到底怎么运行的我也记不清楚了,有空你看下源码吧,或许能找到解决办法

#17


求助各位!!@  楼上所有人!
经过几个月的查找问题,终于发现了原因所在,这个连接会丢失,是因为有人在Oracle数据库把Lock的Session给KILL掉了,只要有一个Session被KILL(即使是INACTIVE的Session),tomcat连接池就会报关闭的连接的错误!

所以求问各位大神,tomcat下的JNDI数据库连接池如何配置数据库连接重连的功能?

#18


楼主你这个监控的工具是什么?谢谢告知

#19


引用 18 楼 baidu_22481969 的回复:
楼主你这个监控的工具是什么?谢谢告知


javaMelody

要不要帮忙我看看这个问题啊,现在还没有解决。就是在数据库中KILL掉SESSION后,连接已经关闭了,但是tomcat认为还是有效的,继续放入连接池中了。。

#20


引用 19 楼 yzjdt 的回复:
Quote: 引用 18 楼 baidu_22481969 的回复:

楼主你这个监控的工具是什么?谢谢告知


javaMelody

要不要帮忙我看看这个问题啊,现在还没有解决。就是在数据库中KILL掉SESSION后,连接已经关闭了,但是tomcat认为还是有效的,继续放入连接池中了。。

我也是遇到相似的问题了,不过我已经排除不是代码的问题了,你看看楼上的几位,要不就是连接池的配置问题。我也还在解决中。。

#21


后来我这里找了很久的错误,发现是因为有时候会有后台数据库死锁的情况,在数据库中KILL掉连接后,就会出现这样的问题;
这个连接池解决不了这个问题,只能优化系统代码,减少数据库死锁情况的出现。感谢这么多大神的关心与回复!

#1


这种现象一般是使用了关闭的Connection,
你仔细检查下代码是不是哪个地方使用了关闭的Connection操作了?

#2


引用 1 楼 luntanrenhaoduo 的回复:
这种现象一般是使用了关闭的Connection,
你仔细检查下代码是不是哪个地方使用了关闭的Connection操作了?


感谢您的回复,就是这一点我很疑惑,JDBCTemplate中是自己封装了关闭数据库的连接,如何能让程序员显性的把JDBCTemplate中使用的Connection关闭呢?

#3


因为你是接手的项目,而不是你自己写的。
有些人在操作SQL时喜欢在程序里自己弄一个Connection进行操作.
而这个Connection是通过JDBCTemplate get到的,又进行了违规的操作.

至于为啥这么写...我觉得你应该去问问给你项目的那个人.

#4


引用 3 楼 luntanrenhaoduo 的回复:
因为你是接手的项目,而不是你自己写的。
有些人在操作SQL时喜欢在程序里自己弄一个Connection进行操作.
而这个Connection是通过JDBCTemplate get到的,又进行了违规的操作.

至于为啥这么写...我觉得你应该去问问给你项目的那个人.


大神,我在我的项目中搜索到了一段代码,麻烦您看下,是不是这样的就会出现这样的问题?


WebApplicationContext ctx = (WebApplicationContext) request.getAttribute("WebApplicationContext");
JdbcTemplate jt = (JdbcTemplate) ctx.getBean("jdbcTemplate");
Connection con = null;
try{
con  = jt.getDataSource().getConnection();
con.setAutoCommit(false);
/**
 * 业务操作
 */
con.setAutoCommit(true);
}catch(Exception e){
e.printStackTrace();
try {
con.setAutoCommit(true);
} catch (SQLException e1) {
e1.printStackTrace();
}
}finally{
DbUtil.closeConnection(con, true);
}

然后上面的DbUtil.closeConnection(con, true);的方法如下:

public static boolean closeConnection(Connection connection,
boolean isExcept) {
/* 331 */boolean status = true;
try {
/* 333 */if ((connection != null) && (!connection.isClosed())) {
/* 334 */if (!connection.getAutoCommit())
try {
/* 336 */if (isExcept)
/* 337 */connection.rollback();
else
/* 339 */connection.commit();
} catch (Exception e) {
/* 341 */status = false;
/* 342 */if (!isExcept)
/* 343 */connection.rollback();
} finally {
/* 345 */connection.setAutoCommit(true);
}
/* 347 */connection.close();
/* 348 */connection = null;
}
} catch (Exception e) {
/* 351 */status = false;
}
/* 353 */return status;
}


再次感谢大神的指导!

#5


你找下 select CNTR_EF_ID from ship_bill where bill_no = ? 这个sql用的会话对象是怎么操作的,不行把这段代码删掉,测试下,会不会报错还.

#6


不需要显示关闭连接的

#7


一个可能的原因是,某个地方的连接没有关闭,导致连接被消耗光了。

#8


引用 5 楼 luntanrenhaoduo 的回复:
你找下 select CNTR_EF_ID from ship_bill where bill_no = ? 这个sql用的会话对象是怎么操作的,不行把这段代码删掉,测试下,会不会报错还.


他这个不仅是这一个地方报错,是有很多地方都报错,我只是把其中一个错误贴出来而已,而且都是一些不相关的业务或者代码都只要用到了JDBCTemplate就会报错;
其中我拿出来的这个报错的地方是这样使用的:


String emptyBillSql = "select CNTR_EF_ID from ship_bill where bill_no = ?";
try {
WebApplicationContext ctx = (WebApplicationContext) request
.getAttribute("WebApplicationContext");
JdbcTemplate jt = (JdbcTemplate) ctx.getBean("jdbcTemplate");
for (String bill : bills) {
if (!StringUtil.isEmpty(bill)) {
bi = bill.split("-");
String billEFId = "F";
try {
billEFId = jt.queryForObject(emptyBillSql, new Object[]{bi[0]}, String.class);
} catch (Exception e) {
e.printStackTrace();
billEFId = "F";
}
// 以下代码省略


有的地方使用的是jt.queryForList 也一样的报错;就是那种突然就出现了,然后后台疯狂报错,全都是关闭的连接这样的错误。所以我也是怀疑是不是因为单例模式的影响,在某个地方把JDBCTemplate的连接关闭了,其他地方只要引用JDBCTemplate就都报错了。
但是我也不知道是什么样的代码能做到把JDBCTemplate的连接关闭而且让Spring不会新获取连接。

#9


引用 6 楼 okafor2011 的回复:
不需要显示关闭连接的


我也查了很多资料是不应该显示的关闭连接;所以我也不确定下面这段代码是不是有问题,也不轻视是否会造成我前面说的那种情况出现:


WebApplicationContext ctx = (WebApplicationContext) request.getAttribute("WebApplicationContext");
JdbcTemplate jt = (JdbcTemplate) ctx.getBean("jdbcTemplate");
Connection con = null;
try{
con  = jt.getDataSource().getConnection();
con.setAutoCommit(false);
/**
 * 业务操作
 */
con.setAutoCommit(true);
}catch(Exception e){
e.printStackTrace();
try {
con.setAutoCommit(true);
} catch (SQLException e1) {
e1.printStackTrace();
}
}finally{
DbUtil.closeConnection(con, true);
}

#10


引用 7 楼 Q80470101 的回复:
一个可能的原因是,某个地方的连接没有关闭,导致连接被消耗光了。


一开始我也以为是这个原因,但是我的连接池设置了500的连接,这是很久以前以为是连接数的问题,所以设了这么大,但是我上面也给出了我们监控系统的图表,今天的最大连接数才19,但是今天就出现两次这样的问题, 我只能重启服务器才能解决。

#11


引用 10 楼 yzjdt 的回复:
Quote: 引用 7 楼 Q80470101 的回复:

一个可能的原因是,某个地方的连接没有关闭,导致连接被消耗光了。


一开始我也以为是这个原因,但是我的连接池设置了500的连接,这是很久以前以为是连接数的问题,所以设了这么大,但是我上面也给出了我们监控系统的图表,今天的最大连接数才19,但是今天就出现两次这样的问题, 我只能重启服务器才能解决。


我建议你去检查下所有jdbc的代码(你们代码中所有的jdbc,不只是JDBCTemplate),你的现象和这个猜测很吻合。
ps: ctrl+shift+g 快捷键可以查看到所有引用。

#12


JdbcTemplate是spring封装的快速操作数据库的一套API,你可以点击进去看下源代码(这里就不提供了,没找到例子,这个东西已经被我们摒弃很多年了),肯定是不需要自己关闭的,而且后面看了下,WebApplicationContext ctx = (WebApplicationContext) request.getAttribute("WebApplicationContext");
JdbcTemplate jt = (JdbcTemplate) ctx.getBean("jdbcTemplate");
Connection con = null;
try{
    con  = jt.getDataSource().getConnection();
    con.setAutoCommit(false);
    /**
     * 业务操作
     */
    con.setAutoCommit(true);
}catch(Exception e){
    e.printStackTrace();
    try {
        con.setAutoCommit(true);
    } catch (SQLException e1) {
        e1.printStackTrace();
    }
}finally{
    DbUtil.closeConnection(con, true);
}
这块好像是要对事物做控制,不知道有AOP这个东西么,这块是线程安全的不,你的问题很可能是线程不安全导致

#13


引用 11 楼 Q80470101 的回复:
Quote: 引用 10 楼 yzjdt 的回复:

Quote: 引用 7 楼 Q80470101 的回复:

一个可能的原因是,某个地方的连接没有关闭,导致连接被消耗光了。


一开始我也以为是这个原因,但是我的连接池设置了500的连接,这是很久以前以为是连接数的问题,所以设了这么大,但是我上面也给出了我们监控系统的图表,今天的最大连接数才19,但是今天就出现两次这样的问题, 我只能重启服务器才能解决。


我建议你去检查下所有jdbc的代码(你们代码中所有的jdbc,不只是JDBCTemplate),你的现象和这个猜测很吻合。
ps: ctrl+shift+g 快捷键可以查看到所有引用。


也就是说如果jdbc的Connection是从JdbcTemplate里面取出来的话,再关闭是很有可能出现这种问题的?

#14


引用 12 楼 xiaohuashenshou 的回复:
JdbcTemplate是spring封装的快速操作数据库的一套API,你可以点击进去看下源代码(这里就不提供了,没找到例子,这个东西已经被我们摒弃很多年了),肯定是不需要自己关闭的,而且后面看了下,WebApplicationContext ctx = (WebApplicationContext) request.getAttribute("WebApplicationContext");
JdbcTemplate jt = (JdbcTemplate) ctx.getBean("jdbcTemplate");
Connection con = null;
try{
    con  = jt.getDataSource().getConnection();
    con.setAutoCommit(false);
    /**
     * 业务操作
     */
    con.setAutoCommit(true);
}catch(Exception e){
    e.printStackTrace();
    try {
        con.setAutoCommit(true);
    } catch (SQLException e1) {
        e1.printStackTrace();
    }
}finally{
    DbUtil.closeConnection(con, true);
}
这块好像是要对事物做控制,不知道有AOP这个东西么,这块是线程安全的不,你的问题很可能是线程不安全导致


当时做这个项目的时候,并没有完全按照Spring的方式来做,就算JDBCTemplate老一点也没什么大问题,但问题就是,他们很多都是把JdbcTemplate转为原始的Connection后再操作,导致这个项目里面最少用了三种JDBC的操作,AOP更加没用上。

然后您说的关于线程的,这个方法并没有加任何synchronized的关键字来控制线程安全,然后我看了一下这段代码,然后也是我的疑惑所在,JdbcTemplate虽然是单例模式,但是不应该是每次我从Spring容器里面取一个JdbcTemplate出来的时候,应该就会向连接池要一个新连接对吧?如果是这样,就算这段代码里面我手动关闭了,应该也不会造成其他地方只要一调用JdbcTemplate就会报错吧?这样的话岂不是JDBCTemplate里面永远只有一个有效的连接?所有地方调用JdbcTemplate都是使用同一个Connection来操作的?

#15


你可以先把手动获取连接的代码先屏蔽,然后观察一段时间看看。

#16


没办法回答你那么详细来了,呵呵,这个东西N多年不用了,里面到底怎么运行的我也记不清楚了,有空你看下源码吧,或许能找到解决办法

#17


求助各位!!@  楼上所有人!
经过几个月的查找问题,终于发现了原因所在,这个连接会丢失,是因为有人在Oracle数据库把Lock的Session给KILL掉了,只要有一个Session被KILL(即使是INACTIVE的Session),tomcat连接池就会报关闭的连接的错误!

所以求问各位大神,tomcat下的JNDI数据库连接池如何配置数据库连接重连的功能?

#18


楼主你这个监控的工具是什么?谢谢告知

#19


引用 18 楼 baidu_22481969 的回复:
楼主你这个监控的工具是什么?谢谢告知


javaMelody

要不要帮忙我看看这个问题啊,现在还没有解决。就是在数据库中KILL掉SESSION后,连接已经关闭了,但是tomcat认为还是有效的,继续放入连接池中了。。

#20


引用 19 楼 yzjdt 的回复:
Quote: 引用 18 楼 baidu_22481969 的回复:

楼主你这个监控的工具是什么?谢谢告知


javaMelody

要不要帮忙我看看这个问题啊,现在还没有解决。就是在数据库中KILL掉SESSION后,连接已经关闭了,但是tomcat认为还是有效的,继续放入连接池中了。。

我也是遇到相似的问题了,不过我已经排除不是代码的问题了,你看看楼上的几位,要不就是连接池的配置问题。我也还在解决中。。

#21


后来我这里找了很久的错误,发现是因为有时候会有后台数据库死锁的情况,在数据库中KILL掉连接后,就会出现这样的问题;
这个连接池解决不了这个问题,只能优化系统代码,减少数据库死锁情况的出现。感谢这么多大神的关心与回复!