java - Java JDBC Single Statement 对象在 while 循环之前和 while 循环内
问题描述
我正在编写一个使用 JDBC 连接到 Oracle 的核心 Java 程序。
- 我正在选择带有选择条件的第一个表以获取少量行 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)
解决方案
在迭代由该语句创建的结果集时,您不能重用该语句,因为在该Statement
对象上执行另一个查询(或任何其他语句类型)将自动关闭先前查询执行的结果集。这是 JDBC API 和规范所要求的。
如果你想这样做,那么你需要禁用 auto-commit* 并使用两个语句对象。
但是,您显示的代码是一种称为 N+1 查询问题的反模式,通常您不应遍历结果集以执行每行的其他单独选择:您可以创建一个为您执行此操作的单个选择语句。这通常表现得更好。
例如,您可以使用:
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 驱动程序在这方面是宽松的,并且结果集不会在自动提交边界上关闭)。
推荐阅读
- oracle - 使用 oracle 在 docker 中运行 flyway 迁移
- redis - Redis.blPop:如何检查有多少进程等待'key'?
- r - R-Project:如何限制 SPI 图中的轴?ylim 和 xlim 不起作用
- selenium - appium android本机应用程序测试中的此会话错误不支持“css选择器”-Java
- electron - 错误:fs.readFileSync 不是使用 Electron 的函数
- java - 尝试从 ArrayList 获取字符串时出现 IndexOutOfBoundsException
- node.js - 使用全球 AuthGuard 自定义护照策略
- django-viewflow - 如何完成所有并行活动 ViewFlow (Terminate End)?
- forms - c ++如何将标签动态添加到组框并设置其位置
- python-3.x - Python:通过 COM 与 Lotus Domino 连接