You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java操作SQLite数据库抛出ResultSet closed异常无法定位原因求解决

根因分析

你遇到的ResultSet closed异常和Statement实例无关,核心问题是**ResultSet取值前没有调用next()方法移动游标到有效行**:
JDBC规范要求executeQuery返回的ResultSet默认游标定位在第一行记录之前,必须调用next()方法且确认返回true(代表存在有效数据行)后,才能调用getInt()/getString()等方法取值。如果查询结果为空、或者未调用next()直接取值,SQLite的JDBC实现会直接关闭结果集,抛出你遇到的异常。

修复方案

修改你报错位置的代码,先判断rsOferta是否存在有效数据再取值,同时增加空结果兜底逻辑:

Statement stat4 = con.createStatement();
ResultSet rsOferta = stat4.executeQuery("SELECT * FROM " + TABLA_OFERTAS + " WHERE " + OFERTAS_COL_TITOR + " = '" + prof + "' AND " + OFERTAS_COL_ASIGNADA + " = 'NON'");
// 新增游标移动与存在性判断
if (rsOferta.next()) {
    int idOfer = rsOferta.getInt(1);
    System.out.println(" idOfer = " + idOfer);
    int numOfer = rsOferta.getInt(2);
    String tutOfer = rsOferta.getString(4);
    String cotutOfer = rsOferta.getString(5);
    rsOferta.close();
    // 原有的UPDATE逻辑保留在if代码块内
    Statement stat3 = con.createStatement();
    stat3.executeUpdate("UPDATE " + TABLA_OFERTAS + " SET " + OFERTAS_COL_ASIGNADA + " = 'OB' WHERE " + OFERTAS_COL_ID + " = '" + idOfer + "'");
    stat3.executeUpdate("UPDATE " + TABLA_OBLIGADOS + " SET " + OBLIGADOS_COL_ASIGNADO + " = 'SÍ' WHERE " + OBLIGADOS_COL_ID + " = '" + rsObligados.getInt(1) + "'");
    stat3.executeUpdate("UPDATE " + TABLA_OBLIGADOS + " SET " + OBLIGADOS_COL_SELECCION + " = " + numOfer + " WHERE " + OBLIGADOS_COL_ID + " = '" + rsObligados.getInt(1) + "'");
    if (cotutOfer.equals("")) {
        stat3.executeUpdate("UPDATE " + TABLA_PROFESORES + " SET " + PROFESORES_COL_TFGS + " = " + PROFESORES_COL_TFGS + " + 1 WHERE " + PROFESORES_COL_NOMBRE + " = '" + tutOfer + "'");
    } else {
        stat3.executeUpdate("UPDATE " + TABLA_PROFESORES + " SET " + PROFESORES_COL_TFGS + " = " + PROFESORES_COL_TFGS + " + 0.5 WHERE " + PROFESORES_COL_NOMBRE + " = '" + tutOfer + "'");
        stat3.executeUpdate("UPDATE " + TABLA_PROFESORES + " SET " + PROFESORES_COL_TFGS + " = " + PROFESORES_COL_TFGS + " + 0.5 WHERE " + PROFESORES_COL_NOMBRE + " = '" + cotutOfer + "'");
    }
    stat3.close();
} else {
    // 无匹配 oferta 时的兜底逻辑,避免程序崩溃
    System.out.println("教授 " + prof + " 无可用的未分配TFG,跳过当前学生分配");
    rsOferta.close();
}

ResultSet使用核心注意事项

  • 同一个Statement执行新的SQL语句时,之前关联的未关闭ResultSet会被自动关闭,涉及多结果集操作时建议创建独立Statement实例
  • ResultSet游标超出有效行范围、关联的Statement/数据库连接关闭时,都会被标记为关闭状态,此时调用取值方法直接抛异常
  • 所有ResultSet取值前必须先调用next()判断存在有效行,哪怕是聚合函数(如MIN/MAX/COUNT)的查询也要加判断,避免空结果报错

额外优化建议

你当前代码存在SQL注入风险、资源未完全释放的问题,建议用Java 7+提供的try-with-resources语法自动管理Statement、ResultSet资源,无需手动关闭也不会漏释放,示例写法:

// try代码块结束后会自动关闭stat4、rsOferta
try (Statement stat4 = con.createStatement();
     ResultSet rsOferta = stat4.executeQuery(查询SQL)) {
    if (rsOferta.next()) {
        // 取值逻辑
    }
} catch (SQLException e) {
    // 异常处理逻辑
}

另外拼接SQL的写法建议替换为PreparedStatement,避免SQL注入风险同时提高执行效率。

内容的提问来源于stack exchange,提问作者Piti

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 02:21:01