Java RuntimeException-耗尽的Resultset-如何发生?

Java RuntimeException-耗尽的Resultset-如何发生?,java,multithreading,exception,resultset,Java,Multithreading,Exception,Resultset,代码: 如您所见,这不是不调用ResultSet.next()的明显问题。不仅如此,我已经在ResultSet中调用了两次getString,这是第三次破坏它 请注意,这是一个偶然的问题,此代码在大多数情况下工作正常 该查询类似于: // Start the query. final ResultSet r = prepared.executeQuery(); try { // Returning false from oneRow will stop the

代码:

如您所见,这不是不调用
ResultSet.next()
的明显问题。不仅如此,我已经在
ResultSet
中调用了两次
getString
,这是第三次破坏它

请注意,这是一个偶然的问题,此代码在大多数情况下工作正常

该查询类似于:

    // Start the query.
    final ResultSet r = prepared.executeQuery();
    try {
      // Returning false from oneRow will stop the process.
      boolean goOn = true;
      while (r.next() && goOn) {
        log.trace("Result: {}", toString(r));
        // We did do at least one.
        ran = true;
        goOn = oneRow(r);
      }
    } finally {
      try {
        // Always remember to close the ResultSet.
        r.close();
      } catch (SQLException ex) {
        log.error("Close failed", ex);
      }
    }

    // Handle one row.
    public boolean oneRow(ResultSet r) throws Exception {
      String xml1 = r.getString(1);
      String xml2 = r.getString(2);
      if (xml1 == null && xml2 == null) {
        // Probably compressed.
        xml1 = decompress(r, 3);
        xml2 = decompress(r, 4);
      }
      return false;
    }

  private static String decompress(ResultSet rs, int col) throws SQLException {
    // Exception gets thrown here!!! ???
    final InputStream compressed = rs.getBinaryStream(col);
    ...
我意识到这是一个相当乱伦的问题,但正如我所说的——大多数情况下,这一切都很好

已添加

根据
user1933888
发布的答案,我突然想到,既然我使用的是一个自制的连接池,那么一条准备好的语句是否可能在共享不同连接的两个线程之间干扰自身


我相信,同一个连接永远不会被两个线程同时使用,但可以共享准备好的语句,因为它应该驻留在数据库中。

由于您的准备好的语句链接到一个连接,如果在线程之间共享PreparedStatement,那么最终将共享一个连接,这肯定会导致问题

的确,语句通常缓存在DB中,以避免重新分析,但每个线程仍然需要一个PreparedStatement对象,以避免混淆DB驱动程序,使其了解线程需要什么

一般来说,我会避免使用自制连接池,因为AppServers通常会为您提供连接池,或者(如果您不在AppServer中)存在大量连接池LIB,那么为什么要重新发明轮子呢

一般而言:

  • 您可以在并发线程之间共享数据源
  • 您不应该在并发线程之间共享Connection、PreparedStatement或ResultSet对象
连接池将确保非并发线程可以重用连接,JDBC驱动程序将在内部缓存语句


希望这是有意义的。

这可能是一些数据问题。您可以显示堆栈跟踪吗?另外,oneRow总是返回false,因此您永远不会处理多行,是这样吗?@beny23-在这种情况下是的-my
Query
类的特殊用途是在产品的详细信息数据库中进行简单的查找。我只想要第一个结果。然后你可以用if替换,而不需要goOn。我还考虑添加条件,告诉db只返回第一行,以避免不必要的数据从db返回。我确信我在另一个站点上看到了一篇帖子(可能是JavaLobble,但我现在找不到)这表明准备好的语句存储在DBMS中,因此,一旦它们被创建,就可以从任何线程/连接访问它们——本质上,它们作为某种形式的计划保存。我很高兴在这一点上得到纠正。+1-我同意家用brew连接池-这是继承的代码,我正在将其切换到适当的池中。。。。也许是。。。当然是,但我仍然找不到引用。这样想:PreparedStatement链接到一个连接(您从中调用prepareStatement的连接)。如果您在并发线程中使用它,那么您将在同一时间使用相同的连接,这将导致麻烦。对日志的一些非常详细的检查显示了一些奇怪的准备语句交叉中毒。本质上,在一个连接上准备的语句似乎偶尔会毒害另一个线程上另一个连接上的同一语句。为了解决这个问题,我将在使用后关闭所有准备好的语句,并使用一个经过测试的连接池(c3p0)。希望这能解决我的问题。
"SELECT P1.XML XML1, "
      + "P2.XML XML2, "
      + "P1.CompressedXML CompressedXML1, "
      + "P2.CompressedXML CompressedXML2 "
      + "FROM Table1 P1 "
      + "LEFT JOIN Table2 T2 ON T2.ID = P1.ID "
      + "LEFT JOIN Table1 P2 ON P2.ID = T2.Item_Code "
      + "WHERE P1.ID = ?"