zoukankan      html  css  js  c++  java
  • 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语句和预编译后的SQ语句不相同
    
    1. 若是在JDBC工具类中将Connection,PreparedStatement或ResultSet定义成全局静态变量,则要考虑线程安全问题,可能会出现上述2的问题,将可能出现线程安全的地方同步即可。

    总结:

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

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

    报错原因:

    ResultSet is from UPDATE. No Data直译后的意思是ResultSet 是来自更新(添加,删除,修改语句)。没有数据。也就是说Result的实例可能是执行增删改的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工具类中将Connection,PreparedStatement或ResultSet定义成全局静态变量,则要考虑线程安全问题,将可能出现线程安全的地方同步即可。

    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工具类中将Connection,PreparedStatement或ResultSet定义成全局静态变量,则要考虑线程安全问题,将可能出现线程安全的地方同步即可。

    总结

    • 先检查SQL语句是否正确
    • 理清链路 加载JDBC驱动 --> Connection --> PreparedStatement --> ResultSet ,先想到最有可能出错的地方,打断点debug进去或控制台打印可能出错的变量
    • 若没有使用数据库连接池,如果JDBC工具类中有静态变量,须考虑线程安全问题,能用数据库连接池尽量使用数据库连接池
  • 相关阅读:
    java学习55天2020/8/29
    java学习51天2020/8/25
    java学习55天2020/8/31
    java学习49天2020/8/23
    java学习52天2020/8/26
    java学习48天2020/8/22
    2020.12.05
    2020.12.04
    2020.12.07
    2020.12.03
  • 原文地址:https://www.cnblogs.com/windowsxpxp/p/12616158.html
Copyright © 2011-2022 走看看