Java 处理后,Resultset和CallableStatement未关闭

Java 处理后,Resultset和CallableStatement未关闭,java,oracle,jdbc,Java,Oracle,Jdbc,我试图在处理后关闭ResultSet和CallableStatement,但只有Connection正在关闭,其他两个没有关闭 final String procedureCall = "{call GET_PAWS_PERSON_DETAILS(?, ?)}"; try { //Get Connection instance from dataSource connection = dataSource.getConnection();

我试图在处理后关闭
ResultSet
CallableStatement
,但只有
Connection
正在关闭,其他两个没有关闭

final String procedureCall = "{call GET_PAWS_PERSON_DETAILS(?, ?)}";
    try {

        //Get Connection instance from dataSource
        connection = dataSource.getConnection();
        callableStatement = connection.prepareCall(procedureCall);
        callableStatement.setString(1, userName);
        callableStatement.registerOutParameter(2, OracleTypes.CURSOR);

        //Call Stored Procedure
        callableStatement.executeUpdate();
        // get cursor and cast it to ResultSet
        resultSet = (ResultSet) callableStatement.getObject(2);
        logger.debug("reslt" + resultSet.getFetchSize());
        // loop it like normal
        while (resultSet.next()) {
            personDTO.setPersonID(resultSet.getString(1));
            personDTO.setFirstName(resultSet.getString(2));
            personDTO.setLastName(resultSet.getString(3));
            personDTO.setFullName(resultSet.getString(4));
            personDTO.setEmail(resultSet.getString(5));
        }

    }catch (SQLException e) {

        e.printStackTrace();

    } finally {
        if(resultSet != null)
            try {
                resultSet.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }

        if(callableStatement != null)
            try {
                callableStatement.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        if(connection != null)
            try {
                connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }

    }
这是我正在使用的代码。关闭后,只需打印
连接
状态
可调用状态
。结果是

Connection : null
Resultset : org.apache.tomcat.dbcp.dbcp.DelegatingResultSet@6f1f6b1e
Callable statement : oracle.jdbc.driver.OracleStatementWrapper@77b1b790.
由于此问题,数据库连接池的大小正在增加

请给我任何人的解决方案

在Tomcat server.xml中

<Resource driverClassName="oracle.jdbc.OracleDriver" maxActive="4" maxIdle="10" maxWait="5000" name="jdbc/epaws" global="jdbc/epaws" 
        password="polusneu" type="javax.sql.DataSource" url="jdbc:oracle:thin:@192.168.1.60:1521:coeusnew" 
        username="polusneu" validationQuery="select 1 from dual" testOnBorrow="true" removeAbandoned="true"
  removeAbandonedTimeout="55"/> 

applicationcontext.xml

<bean id="dbDataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
    <property name="jndiName" value="java:comp/env/jdbc/epaws"/>
    <property name="resourceRef" value="true"/>
    <property name="cache" value="false"/>
    <property name="lookupOnStartup" value="false"/>
    <property name="proxyInterface" value="javax.sql.DataSource"/>
</bean>

首先:

关闭对象不会将该对象引用设置为
null
。所以在结束后你仍然有物体是可以的。但奇怪的是,在。。。但无论如何

最后关闭
块是一个有效的过程,但这是一个老派的过程。Java7引入了一个很棒的新特性,名为
trytwithresource
,它负责关闭,即使是在出现错误的情况下。然后代码看起来像

try(Connection con = dataSource.getConnection();
    CallableStatement callable = con.prepareCall(procedureCall)) {

    callableStatement.setString(1, userName);
    callableStatement.registerOutParameter(2, OracleTypes.CURSOR);

    //Call Stored Procedure
    callableStatement.executeUpdate();
    // get cursor and cast it to ResultSet
    try(ResultSet resultSet = (ResultSet) callableStatement.getObject(2)) {
      logger.debug("reslt" + resultSet.getFetchSize());
      // loop it like normal
      while (resultSet.next()) {
          personDTO.setPersonID(resultSet.getString(1));
          personDTO.setFirstName(resultSet.getString(2));
          personDTO.setLastName(resultSet.getString(3));
          personDTO.setFullName(resultSet.getString(4));
          personDTO.setEmail(resultSet.getString(5));
      }
   } //Don't need another catch
} catch(SQLException e) {
   e.printStackTrace();
} 
首先:

关闭对象不会将该对象引用设置为
null
。所以在结束后你仍然有物体是可以的。但奇怪的是,在。。。但无论如何

最后关闭
块是一个有效的过程,但这是一个老派的过程。Java7引入了一个很棒的新特性,名为
trytwithresource
,它负责关闭,即使是在出现错误的情况下。然后代码看起来像

try(Connection con = dataSource.getConnection();
    CallableStatement callable = con.prepareCall(procedureCall)) {

    callableStatement.setString(1, userName);
    callableStatement.registerOutParameter(2, OracleTypes.CURSOR);

    //Call Stored Procedure
    callableStatement.executeUpdate();
    // get cursor and cast it to ResultSet
    try(ResultSet resultSet = (ResultSet) callableStatement.getObject(2)) {
      logger.debug("reslt" + resultSet.getFetchSize());
      // loop it like normal
      while (resultSet.next()) {
          personDTO.setPersonID(resultSet.getString(1));
          personDTO.setFirstName(resultSet.getString(2));
          personDTO.setLastName(resultSet.getString(3));
          personDTO.setFullName(resultSet.getString(4));
          personDTO.setEmail(resultSet.getString(5));
      }
   } //Don't need another catch
} catch(SQLException e) {
   e.printStackTrace();
} 


不太清楚你说的不关门是什么意思,在变量上使用
close
不会自动将其设置为
null
..?在我的数据库连接池中,每个事务都会创建新实例。这是因为Resultset和Callable语句没有关闭吗?我需要将该问题的明确答案留给对JDBC有更多经验的人,但是,只要在调用
close
时没有看到异常,就应该使用您显示的代码将其清理干净。谢谢Joachim Lsaksonar您是否反复调用此代码,并且连接不足?是什么让你决定他们不会被释放回游泳池?不太确定你说的他们不会关闭是什么意思,在变量上使用
close
不会自动将其设置为
null
..?在我的数据库连接池中,每个事务都会创建新实例。这是因为Resultset和Callable语句没有关闭吗?我需要将该问题的明确答案留给对JDBC有更多经验的人,但是,只要在调用
close
时没有看到异常,就应该使用您显示的代码将其清理干净。谢谢Joachim Lsaksonar您是否反复调用此代码,并且连接不足?是什么使您确定它们不会释放回池?当然,Jan..会尝试。谢谢。连接后,请关闭用户存在的数据库连接池。它没有删除。这导致maxconnection错误。我的数据库连接轮询maxactive为4。因此,为什么不删除它。如果知道,请给我一个解决方案关闭a来自池的连接将返回到该池。您是否检查了所有从游泳池借用连接的地方?大多数池都有未返回连接的日志记录。我在顶部添加了配置。Iam使用tomcat server.xml设置连接池,使用应用程序上下文设置jndi数据源,并且每个类都调用了数据源。@Jan,您是对的,JDK 1.7支持的自动关闭功能会自动关闭所有资源。应该尽可能地使用它。尝试将MaxWait从5000减少到一个较小的值,然后查看是否释放连接。另外,尝试设置一些超时属性来清理连接。此外,您还可以使用通用连接池(UCP),它是一个Java连接池。请参阅“UCP with tomcat”(www.oracle.com/technetwork/database/application development/planned-unplanned-rlb-UCP-tomcat-2265175.pdf)有关其在Tomcat中配置的更多详细信息,请参阅白皮书。当然,Jan..将尝试。谢谢。连接后,请关闭用户存在的数据库连接池。它没有删除。这导致了maxconnection错误。我的数据库连接轮询maxactive为4。因此,为什么它没有删除。如果知道,请给我一个解决方案关闭池中的连接我会把它放回那个游泳池。您是否检查了所有从游泳池借用连接的地方?大多数池都有未返回连接的日志记录。我在顶部添加了配置。Iam使用tomcat server.xml设置连接池,使用应用程序上下文设置jndi数据源,并且每个类都调用了数据源。@Jan,您是对的,JDK 1.7支持的自动关闭功能会自动关闭所有资源。应该尽可能地使用它。尝试将MaxWait从5000减少到一个较小的值,然后查看是否释放连接。另外,尝试设置一些超时属性来清理连接。此外,您还可以使用通用连接池(UCP),它是一个Java连接池。请参阅“UCP withTomcat”(www.oracle.com/technetwork/database/application development/planned-unplanned-rlb-UCP-tomcat-2265175.pdf)白皮书,了解其在tomcat中配置的更多详细信息。