SQL ResultSet突然关闭

时间:2015-01-16 13:42:35

标签: java mysql sql jdbc resultset

Hello Stackoverflow用户,

我目前遇到SQL连接问题。首先,这是连接器的处理方式

package com.rs.utils.sql;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;

import com.rs.utils.Logger;

public class DatabaseManager {

private String host;
private String database;
private String username;
private String password;

private Connection connection;
private PreparedStatement statement;

private boolean connected;

public DatabaseManager() {
this.host = "";// Settings.DB_HOST;
this.database = "";// Settings.DB_NAME;
this.username = "";// Settings.DB_USER;
this.password = "";// Settings.DB_PASS;
this.connected = false;
}

public void connect() {
    try {
        connection = DriverManager.getConnection("jdbc:mysql://" + host
                + "/" + database
                + "?jdbcCompliantTruncation=false&autoReconnect=true",
                username, password);
        Logger.info("Successfully connected with " + host + "/" + database);
        connected = true;
    } catch (Exception e) {
        Logger.info("Unable to connect with " + host + "/" + database + ".");
        connected = false;
    }
}

public ResultSet executeQuery(String query) {
    try {

        if (!connected())
            return null;

        statement = connection.prepareStatement(query);
        ResultSet results = statement.executeQuery();
        return results;
    } catch (Exception e) {
        Logger.handle(e);
    }
    return null;
}

public int executeUpdate(String query) {
    try {

        if (!connected())
            return 0;

        statement = connection.prepareStatement(query);
        return statement.executeUpdate();
    } catch (Exception e) {
        Logger.handle(e);
    }

    return 0;
}

public boolean connected() {
    return connected;
}

public PreparedStatement statement() {
    return statement;
}

}

使用DatabaseManager实例将大量查询发送到数据库,例如:

databaseManager.executeUpdate(query);    

databaseManager定义为:

private static DatabaseManager databaseManager = new DatabaseManager();    

我得到以下Throwable:

java.sql.SQLException: Operation not allowed after ResultSet closed
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1074)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:988)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:974)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:919)
at com.mysql.jdbc.ResultSetImpl.checkClosed(ResultSetImpl.java:803)
at com.mysql.jdbc.ResultSetImpl.findColumn(ResultSetImpl.java:1126)
at com.mysql.jdbc.ResultSetImpl.getString(ResultSetImpl.java:5732)
at com.rs.utils.sql.PlayerSaving.load(PlayerSaving.java:362)
at com.rs.utils.sql.PlayerLoader.load(PlayerLoader.java:90)    

PlayerLoader中的加载方法:

public static boolean load(Player player, boolean lobby) {
    ResultSet result = null;
    try {
        final long current = System.currentTimeMillis();
        result = World.database().executeQuery("SELECT " + (lobby ? "displayName, rights" : "*") + " FROM " + PLAYER_TABLE + " WHERE username='" + player.getPlayerDefinition().username() + "' LIMIT 1");

        if (!result.next()) {
            return false;
        }

        if (lobby) {
            player.getPlayerDefinition().setRights(result.getInt("rights")).setDisplayName(result.getString("displayName"));
        } else {
            **player.playerSaving().load(result);**
        }

        Logger.log("Loader", "Player loaded in " + (System.currentTimeMillis() - current) + "ms.");
        return true;
    } catch (Exception e) {
        Logger.log("Loader", "Unable to load player profile.");
        Logger.handle(e);
        System.err.println("Error Loading the account.");
    } finally {
        try {
            if (result != null) {
                result.close();
            }
            result = null;
            World.database().statement().close();
        } catch (SQLException e) {
            Logger.handle(e);
        }
    }
    return false;
}    

PlayerSaving加载方法只是将另一个类实例分配给数据库中的值与result.getInt(“rowName”)等,在ResultSet上收到,它超过250行

ResultSet在大多数情况下都很好,这是一个非常罕见的事件,比如100次登录尝试中的1次。但不知何故,ResultSet在变量赋值的中间被关闭,比如,它分配200个变量中的100个,然后ResultSet突然关闭并抛出异常。

有什么想法吗?

1 个答案:

答案 0 :(得分:0)

关闭语句也将关闭基础ResultSet。你可能已经嵌套了对DatabaseManager的调用,这个调用只有一个共享的PreparedStatement,在我看来,这是一个坏主意。

(我没有足够的代表来添加评论,所以我不得不将其作为答案发布)

下面是为每个查询操作使用专用PreparedStatement和ResultSet的示例实现:

public List<MyDataClass> listMyData(Connection con, String partNumber) {
    ArrayList<MyDataClass> list = new ArrayList<MyDataClass>();
    PreparedStatement ps = null;
    ResultSet rs = null;

    try {
        ps = con.prepareStatement("SELECT PART_NO, DESC, PRICE FROM MYTABLE WHERE PART_NO = ?");
        ps.setString(1, partNumber);
        rs = ps.executeQuery();
        while(rs.next()) {
            MyDataClass myData = new MyDataClass();
            myData.setPartNumber(rs.getString("PART_NO"));
            myData.setDescription(rs.getString("DESC"));
            myData.setPrice(rs.getBigDecimal("PRICE"));
            list.add(myData);
        }
        con.commit();
    }
    catch(Throwable thrown) {
        try{ con.rollback(); }catch(Throwable t){}
        //Handle the exception here to log etc.
    }
    finally {
        //Always close result set before statement
        if(rs != null) { try{ rs.close(); }catch(Throwable t){} }
        if(ps != null) { try{ ps.close(); }catch(Throwable t){} }
    }

    return list;
}