Operation not allowed after ResultSet closed,ResultSet is from UPDATE. No Data和Column 'xx' not found

本文详细解析并提供了解决JDBC编程中常见的错误方法,包括ResultSet关闭后操作、执行更新语句后尝试读取结果集及列未找到等问题,通过调整代码逻辑和增强线程安全性来避免这些错误。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Operation not allowed after ResultSet closed,ResultSet is from UPDATE. No Data和Column ‘xxx’ not found报错的解决方法

1. Operation not allowed after ResultSet closed的解决方法

报错原因:

Operation not allowed after ResultSet closed翻译后的意思是**ResultSet关闭后不允许操作**,也就是说在ResultSet的实例调用close()方法后,又再次使用了该实例。

解决思路:

  • 查看报错处的ResultSet实例是否已经调用过close()方法关闭
  • 报错处的ResultSet实例是否和其他ResultSet实例来自的是同一个Connection实例,就是说一个Connection实例执行完不同的sql语句后返回不同ResultSet实例。查看该Connection实例是否同时执行不同sql语句返回ResultSet实例

解决方法:

  1. 先查看ResultSet实例是否已经调用了close()方法,即rs.close()

  2. ResultSet实例并未调用close()方法,则查看生成该ResultSet实例的Connection实例,该Connection实例是否还执行过其他sql语句。若有则查看该Connection实例是否同时执行了多条sql语句。若同时执行了多条sql语句,则需要在获取数据库连接到执行sql语句的流程加上synchronized关键字Connection实例在执行某个sql语句时,不让Connection实例同时执行其他的sql语句,因为一个Connection实例可以对应多个Statement实例或PreparedStatement实例,但一个Statement实例或PreparedStatement实例只能对应一个ResultSet实例。若同一个Connection实例用同一个Statement实例或PreparedStatement实例执行不同sql语句,则两个sql语句生成了一个ResultSet实例。

  3. ResultSet实例并没有调用了close()方法,但又觉得不是该Connection实例并未执行过多条sql语句,则debug查看Statement实例或PreparedStatement实例是否同时进入了多条sql语句,或在控制台中打印Statement实例或PreparedStatement实例执行的sql语句。

    控制台打印Statement实例或PreparedStatement实例执行的sql语句代码如下:

    /***
     * 执行查询的sql语句,并返回结果集
     * @param sql       sql语句
     * @param objects   替代占位符的数组
     * @return ResultSet结果集
     */
    public static ResultSet executeQuery(String sql, Object... objects) {
        System.out.println("sql ->" + sql);
        connection = getConnection();
        System.out.println("connection->" + connection);
        try {
            ppstmt = connection.prepareStatement(sql);
            System.out.println(sql + " ppstm1->" + ppstmt);
    
            if (objects != null && objects.length > 0) {
                for (int i = 0; i < objects.length; i++) {
                    ppstmt.setObject(i + 1, objects[i]);
                }
            }
            rs = ppstmt.executeQuery();
            System.out.println(sql + " ppstm->" + ppstmt);
        } catch (SQLException e) {
            System.out.println("SQL语句错误或参数个数与占位符不一致");
            e.printStackTrace();
            return rs;
        }
        return rs;
    }
    

    报错时截图:

    在这里插入图片描述

    可以看到sql语句和预编译后的sql语句不相同

  4. 若是在JDBC工具类中将ConnectionPreparedStatementResultSet定义成全局静态变量,则要考虑线程安全问题,可能会出现上述2的问题,将可能出现线程安全的地方同步即可。

总结:

  • 先查看是否手动调用过ResultSetclose()方法
  • 若没有,则查看ResultSet实例是否只对应一个Statement实例或PreparedStatement实例
  • 若定义了全局静态变量,考虑线程安全问题

2. ResultSet is from UPDATE. No Data的解决方法

报错原因:

ResultSet is from UPDATE. No Data直译后的意思是ResultSet 是来自更新(添加,删除,修改语句)。没有数据。也就是说ResultSet的实例可能是执行增删改的sql语句(该sql语句不是查询语句),或者是查询语句但ResultSet实例调用next()方法后没有数据,即while(rs.next())中的rs没有数据,所以调用next()方法会报错。

解决思路:

  • 检查sql语句是否正确
  • 使用executegetResultSet方法
  • 查看创建ResultSet实例的代码是否有问题,并一级一级往里追原因

解决方法:

  1. 检查SQL语句,只有查询语句执行后才会返回ResultSet
  2. 使用execute和getResultSet方法
  3. 若SQL语句正确,能在数据库中执行该SQL语句,但Java中却不行,则往上追到PreparedStatement或Statement。debug进入或在控制台打印传入的SQL语句和编译的SQL语句是否相同,若不相同,则是同一时间进入了多条SQL语句,考虑线程安全问题。在需要同步的代码块加上synchronized关键字。
  4. 若是在JDBC工具类中将ConnectionPreparedStatementResultSet定义成全局静态变量,则要考虑线程安全问题,将可能出现线程安全的地方同步即可。

3. Column ‘xxx’ not found的解决方法

报错原因:

Column 'xxx' not found直译的意思就是没有找到xxx这一列,也就是说,查询的结果中,没有该字段的列。

解决思路:

  • 检查sql语句是否正确
  • 检查编译后的sql语句是否和预期的sql语句相同

解决方法:

  1. 检查SQL语句是否正确,比如select name from user;,在Java中却是rs.getString("password");,或者是select nam from user;,在Java中rs.getString("name");认真检查一下修改即可。
  2. debug进入PreparedStatement或Statement,或控制台打印PreparedStatementStatement编译后的sql语句和传入的sql语句是否相同

报错截图:

在这里插入图片描述

上图可知传入的sql语句和编译后的sql语句不同

再看下报错处的代码

/**
 * 查找所有学生
 *
 * @return 学生集合
 */
@Override
public ArrayList<Student> selectAllStudent() {
    String sql = "SELECT * FROM db_studentinfo";
    ArrayList<Student> studentList = null;
    ResultSet rs = JDBCUtil.executeQuery(sql);
    try {
        studentList = new ArrayList<Student>();
        while (rs.next()) {
            studentList.add(setStudent(rs));
        }
    } catch (SQLException e) {
        e.printStackTrace();
        return studentList;
    } finally {
        JDBCUtil.closeDB();
    }
    return studentList;
}

// 将查询的结果集放入学生对象中
private Student setStudent(ResultSet rs) {
    Student student = null;
    try {
        student = new Student();
        student.setStudentNum(rs.getInt("学生学号"));
        student.setStudentName(rs.getString("学生姓名"));
        student.setGrade(rs.getString("年级"));
        student.setStudentClass(rs.getString("班级"));
        student.setSex(rs.getString("性别"));
        student.setAge(rs.getInt("年龄"));
        student.setAddress(rs.getString("家庭住址"));
        student.setPhone(rs.getString("联系电话"));
    } catch (SQLException e) {
        e.printStackTrace();
        return student;
    }
    return student;
}

因为此时是两条sql语句同时进入PreparedStatement实例中,所以虽然传入的是正确的sql语句,但是由于其他的sql语句也进入了,所以导致查询返回的结果集并不是我们一开始传入的sql语句的结果集,故会报

Column '学生学号' not found.的错误。从线程安全方面排查原因,比如在可能导致两条sql语句同时进入PreparedStatement实例的代码块中加synchronize关键字进行同步。

  1. 若是在JDBC工具类中将ConnectionPreparedStatementResultSet定义成全局静态变量,则要考虑线程安全问题,将可能出现线程安全的地方同步即可。

总结

  • 先检查SQL语句是否正确
  • 理清链路 加载JDBC驱动 --> Connection --> PreparedStatement --> ResultSet ,先想到最有可能出错的地方,打断点debug进去或控制台打印可能出错的变量
  • 若没有使用数据库连接池,如果JDBC工具类中有静态变量,须考虑线程安全问题,能用数据库连接池尽量使用数据库连接池
`java.sql.SQLException: ResultSet operation not allowed after ResultSet closed` 这是一个常见的 SQL 异常错误提示,表示尝试对已经关闭的 `ResultSet` 对象进行操作。 ### 原因分析 1. **资源未正确管理**:通常在数据库查询完成后,`ResultSet`, `Statement` `Connection` 都需要手动关闭。如果过早地关闭了 `ResultSet` 或其关联的 `Statement`、`Connection`,那么后续对该 `ResultSet` 的访问就会抛出这个异常。 2. **游标的生命周期结束**:SQL 查询结果是由数据库服务器返回的一个“指针”或“游标”,当该游标被显式或隐式关闭后,再次对其进行读取会失败。 3. **连接池的行为影响**:如果你使用的是一种数据库连接池技术,在某些框架下可能会自动回收关闭底层的对象,而此时程序仍试图继续处理已关闭的结果集。 ### 解决方案 为了避免上述问题发生,请注意以下几点: - 确保所有相关的对象 (`ResultSet`, `Statement`, `PreparedStatement`) 按正确的顺序关闭,并尽量靠近它们作用域末端的位置释放; - 尽量将数据从 `ResultSet` 中提取出来并存储到本地变量或其他结构(如 List<Map<String, Object>>),然后再断开与数据库之间的物理链接; ```java try (Connection conn = DriverManager.getConnection(DB_URL); Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery("SELECT * FROM table")) { while(rs.next()){ // Process each row... } } catch(SQLException e){ System.err.println(e.getMessage()); } ``` 通过使用 Java7+ 推荐的 try-with-resources 自动化机制可以有效避免内存泄漏及类似本题这样的运行期错误情况出现。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值