在while循环之前和while循环内部的Java JDBC Single Statement对象

时间:2019-03-15 00:29:58

标签: java jdbc resultset multiple-resultsets

我正在用JDBC编写一个核心Java程序来连接到Oracle。

  • 我正在选择具有选择条件的“我的第一个”表以获取少量行ID。我在结果集中选择了一些记录
  • 现在我要在while循环(while resultSet.next())中循环结果集
  • 然后为ID等于第一个结果集中的ID的行选择第二张表

在两个选择中,我都使用相同的Statement对象。运行程序时,我仅获得第一行详细信息,然后Java抛出结果集关闭的错误

简而言之,我想知道是否可以在循环之前和循环内部使用单个Statement对象?

下面是我的代码示例

allCOBbatchRSet=stmt.executeQuery("SELECT RECID FROM V_F_BATCH WHERE BATCH_STAGE IS NOT NULL");
while (allCOBbatchRSet.next())
{
        BatchRSet=stmt.executeQuery("SELECT XMLRECORD FROM F_BATCH WHERE RECID="+cobBatchRecId);
        BatchRSet.next();
        ............
}

失败,例外

java.sql.SQLException: Closed Resultset: next at
oracle.jdbc.driver.InsensitiveScrollableResultSet.ensureOpen(InsensitiveScrollableResultSet.java:109) at
oracle.jdbc.driver.InsensitiveScrollableResultSet.next(InsensitiveScrollableResultSet.java:398) at
com.manohar.t24.COBDetails.getCOBDetails(COBDetails.java:46) 

1 个答案:

答案 0 :(得分:0)

在遍历由该语句创建的结果集时,您无法重用该语句,因为对该Statement对象执行另一个查询(或任何其他语句类型)将自动关闭先前查询执行的结果集。这是JDBC API和规范所必需的。

如果要执行此操作,则需要禁用自动提交*并使用两个语句对象。

但是,您显示的代码是一种称为N + 1查询问题的反模式,通常,您不应循环遍历结果集以执行每行其他单独的选择:您可以创建一个执行该操作的单个select语句为了你。这通常会好很多。

例如,您可以使用:

select V_F_BATCH.RECID, F_BATCH.XMLRECORD 
from V_F_BATCH
inner join F_BATCH
  on F_BATCH.RECID = V_F_BATCH.RECID
where V_F_BATCH.BATCH_STAGE is not NULL 

这还将避​​免您当前代码中可能出现的SQL注入问题。


*:禁用自动提交是必要的,因为JDBC要求任何语句执行都必须以自动提交模式提交。提交也将关闭打开的结果集,除非它们对提交而言是可保留的(尽管某些JDBC驱动程序对此宽松,并且结果集不会在自动提交边界上关闭)。