2015-01-16 5 views
0

Привет, пользователи Stackoverflow,SQL ResultSet закрытие suddently

У меня возникла проблема с моим 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 прекрасно работает большую часть времени, это очень редкое событие, например, 1 из 100 попыток входа в систему. Но почему-то ResultSet закрывается посередине назначений переменных, например, он назначает 100 из 200 переменных, затем ResultSet закрывается с трудом и генерирует исключение.

Любые идеи?

+0

Ошибка самообслуживания «Операция не разрешена после закрытия ResultSet», поэтому вы читаете значение, пока оно уже закрыто. @Tom Lima – HaveNoDisplayName

+0

Да, но он закрывается, я не прошу его закрыть, как вы можете видеть, мой код считывает все значения, присваивает значения из базы данных новому экземпляру класса (ints, string, longs и т. д.), затем в финале Блокировка закрывает ResultSet. –

+0

Pls обеспечивает реализацию метода player.playerSaving(). Load (result). – flo

ответ

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; 
} 
+0

Я действительно плохо разбираюсь в базах данных, так как я просто изменил свой сервер данных от Serialization до SQL. Можете ли вы дать мне пример того, как использовать новый PreparedStatement для каждого запроса? –

+0

Я добавил пример к моему отзыву выше – Palamino

+0

Я думаю, что получил его. Изменение кода прямо сейчас. Я добавил метод PreparedStatement к методу загрузки, создав геттер, чтобы получить соединение в экземпляре DatabaseManager, поэтому я звоню из connection.prepareStatement. Я посмотрю, работает ли это. –

Смежные вопросы