Java SQLException:结果集已关闭的问题

时间:2011-10-25 18:18:42

标签: java mysql exception

我有这个java函数运行并产生错误。我无法弄清楚为什么会发生这种情况,因为这是程序中第一个运行的函数,因此没有打开其他连接,语句或结果集。错误是

Operation not allowed after ResultSet closed
java.sql.SQLException: Operation not allowed after ResultSet closed
        at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1055)
        at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:956)
        at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:926)
        at com.mysql.jdbc.ResultSetImpl.checkClosed(ResultSetImpl.java:768)
        at com.mysql.jdbc.ResultSetImpl.next(ResultSetImpl.java:7008)
        at equipmentinventoryimporter.Importer.sqlTable(Importer.java:219)
        at equipmentinventoryimporter.Importer.main(Importer.java:58)

,功能是

private static void sqlTable(SQLTableJob sqltableJob) {
        try {
            Class.forName("com.mysql.jdbc.Driver").newInstance();
            Connection connMySQL2 = null;
            Statement stntMySQL2 = null;
            try {
                connMySQL2 = DriverManager.getConnection(mysqlAddress, mysqlUsername, mysqlPassword);
                stntMySQL2 = connMySQL2.createStatement();
                //MySQL Transaction
                System.out.println("Starting " + sqltableJob.getMysqlTable() + " transaction");
                stntMySQL2.execute("START TRANSACTION");
                String insertQuery = "";
                try {
                    final String inactiveQuery = "UPDATE `" + sqltableJob.getMysqlSchema() + "`.`" + sqltableJob.getMysqlTable() + "` SET `active`=0";
                    stntMySQL2.executeUpdate(inactiveQuery);
                    final ResultSet rs2 = stntMySQL2.executeQuery(sqltableJob.getSQLSelectQuery());
                    int counter = 0;
                    while (rs2.next()) {
                        counter++;
                        final String mysqlSetClause = sqltableJob.getMysqlSetClause(rs2);
                        insertQuery = "INSERT INTO `" + sqltableJob.getMysqlSchema() + "`.`" + sqltableJob.getMysqlTable() + "` SET " +
                                mysqlSetClause +
                                " ON DUPLICATE KEY UPDATE " +
                                mysqlSetClause;
                        stntMySQL2.executeUpdate(insertQuery);
                        if (counter % 5000 == 0) {
                            System.out.println("Processed " + counter + " rows.");
                        }
                    }
                    rs2.close();

                    if (!sqltableJob.isKeepInactives()) {
                        final String deleteQuery = "DELETE FROM `" + sqltableJob.getMysqlSchema() + "`.`" + sqltableJob.getMysqlTable() + "`" +
                                "WHERE `active`=0";
                        stntMySQL2.executeUpdate(deleteQuery);
                    }

                    stntMySQL2.execute("COMMIT");//last line of try block
                    System.out.println("Committed " + sqltableJob.getMysqlTable() + " transaction");
                } catch (Exception ex) {
                    System.out.println(ex.getMessage());
                    ex.printStackTrace();
                    System.out.println("Transaction level exception thrown.");
                    System.out.println(insertQuery);
                    stntMySQL2.execute("ROLLBACK");
                    System.out.println("MySQL query rolled back.");
                }
            //Another MySQL Transaction goes here
            } catch (Exception ex) {
                System.out.println(ex.getMessage());
                ex.printStackTrace();
                System.out.println("Connection level exception thrown.");
            } finally {
                if (stntMySQL2 != null) {
                    try {
                        stntMySQL2.close();
                    } catch (Exception ex) {
                    }
                }
                if (connMySQL2 != null) {
                    try {
                        connMySQL2.close();
                    } catch (Exception ex) {
                    }
                }
            }
        } catch (Exception ex) {
            System.out.println(ex.getMessage());
            ex.printStackTrace();
            System.out.println("Program level exception thrown.");
        }
    }

SQLTableJob是

package equipmentinventoryimporter;

import java.sql.ResultSet;
import java.sql.SQLException;
/**
 *
 * @author jmgreen
 */
public interface SQLTableJob {

    public String getMysqlSchema();

    public String getMysqlTable();

    public String getSQLSelectQuery();

    public String getMysqlSetClause(ResultSet rs) throws SQLException;

    public boolean isKeepInactives();
}

并且引用的特定SQLTableJob是

public class SQLTableJob10I implements SQLTableJob{

public boolean isKeepInactives() {
        return true;
    }

    public String getMysqlSchema() {
        return "Temp_Equipment_Inventory";
    }

    public String getMysqlTable() {
        return "PC_Combined";
    }

    public String getSQLSelectQuery() {
        final String sqlSelectQuery = "SELECT *" +
                " FROM Temp_Equipment_Inventory.PC_Table10i";
        return sqlSelectQuery;
    }

    public String getMysqlSetClause(ResultSet rs) throws SQLException {
        final String mysqlSetClause =
                "`Account_No`=" + Importer.sqlChar(rs.getString("Account_No")) +
                ",`Inventory_No`=" + Importer.sqlChar(rs.getString("Inventory_No")) +
                ",`Building_No`=" + Importer.sqlChar(rs.getString("Building_No")) +
                ",`Location`=" + Importer.sqlChar(rs.getString("Location")) +
                ",`FYYR_No`=" + Importer.sqlChar(rs.getString("FYYR_No")) +
                ",`Cost`=" + Importer.sqlChar(rs.getString("Cost")) +
                ",`Name`=" + Importer.sqlChar(rs.getString("Name")) +
                ",`Desc1`= ''" +
                ",`Desc2`= ''" +
                ",`Desc3`= ''" +
                ",`CDCATY`=" + Importer.sqlChar(rs.getString("CDCATY")) +
                ",`CDSRCE`=" + Importer.sqlChar(rs.getString("CDSRCE")) +
                ",`FLDCAL`=" + Importer.sqlChar(rs.getString("FLDCAL")) +
                ",`CDACQN`=" + Importer.sqlChar(rs.getString("CDACQN")) +
                ",`FLOWNR`=" + Importer.sqlChar(rs.getString("FLOWNR")) +
                ",`FLSHAR`=" + Importer.sqlChar(rs.getString("FLSHAR")) +
                ",`CDDELT`=" + Importer.sqlChar(rs.getString("CDDELT")) +
                ",`CNYTDT`=" + Importer.sqlChar(rs.getString("CNYTDT")) +
                ",`NOPURO`=" + Importer.sqlChar(rs.getString("NOPURO")) +
                ",`NOPIMO`=" + Importer.sqlChar(rs.getString("NOPIMO")) +
                ",`CDPREI`=" + Importer.sqlChar(rs.getString("CDPREI")) +
                ",`Original_Amount`=" + Importer.sqlChar(rs.getString("Original_Amount")) +
                ",`Serial_Code`=" + Importer.sqlChar(rs.getString("Serial_Code")) +
                ",`CDCOMP`=" + Importer.sqlChar(rs.getString("CDCOMP")) +
                ",`NOCHECK`=" + Importer.sqlChar(rs.getString("NOCHECK")) +
                ",`CDCOMM`=" + Importer.sqlChar(rs.getString("CDCOMM")) +
                ",`Last_Update`=" + Importer.sqlDate(rs.getString("Last_Update")) +
                ",`CDDEPT`=" + Importer.sqlChar(rs.getString("CDDEPT")) +
                ",`Room_No`=" + Importer.sqlChar(rs.getString("Room_No")) +
                ",`Date_Scanned`=" + Importer.sqlDate(rs.getString("Date_Scanned")) +
                ",`Date_Acquired`=" + Importer.sqlDate(rs.getString("Date_Acquired")) +
                ",`Manufacturer_Name`=" + Importer.sqlChar(rs.getString("Manufacturer_Name")) +
                ",`Expiry_Date`=" + Importer.sqlDate(rs.getString("Expiry_Date")) +
                ",`Active`='1'";
        return mysqlSetClause;
    }
}

1 个答案:

答案 0 :(得分:4)

来自Javadoc

  

当生成它的ResultSet对象关闭,重新执行或用于从多个结果序列中检索下一个结果时,Statement对象会自动关闭。

从你的代码:

                stntMySQL2.executeUpdate(inactiveQuery);
                final ResultSet rs2 = stntMySQL2.executeQuery(sqltableJob.getSQLSelectQuery());
                while (rs2.next()) {
                    ...
                    stntMySQL2.executeUpdate(insertQuery);

您正在循环中重新执行stntMySQL2。这会自动关闭rs2

要修复,请在循环中使用不同的语句对象。