【问题标题】:ResultSet Object is closed - jtdsResultSet 对象已关闭 - jtds
【发布时间】:2011-11-10 15:38:04
【问题描述】:

我使用 JTDS 连接到 MS-SQL 2005。我使用 c3p0 作为 DB 连接池,使用 Spring 配置。

我在一个 Groovy 脚本中随机收到一个 SQLException:Invalid state, the ResultSet object is closed,我在其中传递了对连接池的引用。该脚本每隔一段时间由一个计时器执行。随机,我的意思是脚本在 99% 的情况下都能完美运行,但是当它失败时,它会这样做几次,然后再次恢复正常工作,从中断的地方继续工作。所有关键工作都在事务中完成,从消息队列中拉出。

逻辑如下:

    //passed into the groovy context
    DataSource source = source;
    Connection conn = source.getConnection();

    ...
    //Have to omit proprietary DB stuff... sorry...
    PreparedStatement fooStatement = conn.prepareStatement("INSERT INTO foo (x,y,z) VALUES (?,?,?) select SCOPE_IDENTITY();");        
    ResultSet identRes = fooStatement.executeQuery();

    //This is where the execption is thrown.
    identRes.next();

    ...

    try{
         log.info("Returning SQL connection.");
         conn.close();
    }catch(Exception ex){}

有一个单独的计时器线程运行类似的 groovy 脚本,我们在其中没有看到这个问题。该脚本使用类似的调用来获取连接并关闭它。

最初,我们认为第二个脚本可能已经从池中获取相同的连接,先完成,然后关闭连接。但是 c3p0 的文档说调用 conn.close() 应该简单地将其返回到池中。

有没有其他人看到这个,或者我在这里错过了什么重要的东西?

谢谢。

【问题讨论】:

  • 这应该没问题,总而言之。 identRes.hasNext() 返回什么?此外,请确保在 finally 块中关闭连接。
  • 是的,我忘了添加它在 finally 块中的事实。不得不从脚本中复制代码。 identRes 应该包含一个列,即用于前一个插入的标识,它为我提供了将另一个插入映射到另一个表的引用(Hibernate 使用它,实际上是从他们的源中发现了 SCOPE_IDENTITY() 调用。)跨度>

标签: java sql-server-2005 jdbc c3p0 jtds


【解决方案1】:

我们解决了这个问题... C3P0 被配置为丢弃签出时间超过 30 秒的连接,我们这样做是为了防止数据库中的死锁(我们不控制调整)。其中一项事务需要很长时间才能完成,并且 C3P0 正在断开连接,从而导致 ResultSet Closed 错误。然而,令人惊讶的是,C3P0 没有记录该事件,因此我们没有在应用程序的日志中看到这一点。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-06-19
    • 2018-08-16
    • 2018-09-17
    • 2019-04-05
    • 2012-04-14
    • 2016-08-16
    • 1970-01-01
    相关资源
    最近更新 更多