2013-04-22 20 views
5

私はこの1日半近く作業しており、このエラーを解決できないようです。なぜResultSetが閉じられているのかわかりません。多分あなたの何人かが私を助けることができます。Java JDBC MySQLの例外:「ResultSetが終了した後に操作が許可されていません」

MySQLDatabase:

package net.gielinor.network.sql; 

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

public abstract class MySQLDatabase { 

    private String host; 
    private String database; 
    private String username; 
    private String password; 
    private Connection connection = null; 
    private Statement statement; 

    public MySQLDatabase(String host, String database, String username, String password) { 
     this.host = host; 
     this.database = database; 
     this.username = username; 
     this.password = password; 
    } 

    public abstract void cycle() throws SQLException; 

    public abstract void ping(); 

    public void connect() { 
     try { 
      Class.forName("com.mysql.jdbc.Driver").newInstance(); 
      connection = DriverManager.getConnection(String.format("jdbc:mysql://%s/%s", host, database), username, password); 
      statement = connection.createStatement(); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
    } 

    public void ping(String table, String variable) { 
     try { 
      statement.executeQuery(String.format("SELECT * FROM `%s` WHERE `%s` = 'null'", table, variable)); 
     } catch (Exception e) { 
      connect(); 
     } 
    } 

    public ResultSet query(String query) throws SQLException { 
     if (query.toLowerCase().startsWith("select")) { 
      return statement.executeQuery(query); 
     } else { 
      statement.executeUpdate(query); 
     } 
     return null; 
    } 

    public Connection getConnection() { 
     return connection; 
    } 

} 

MySQLHandler

package net.gielinor.network.sql; 

import java.io.FileInputStream; 
import java.util.ArrayList; 
import java.util.List; 
import java.util.Properties; 

import net.gielinor.network.sql.impl.MySQLDonation; 

public class MySQLHandler extends Thread { 

    private static final MySQLHandler mysqlHandler = new MySQLHandler(); 

    public static MySQLHandler getMySQLHandler() { 
     return mysqlHandler; 
    } 

    private static List<MySQLDatabase> updateList; 
    private static String host; 
    private static String database; 
    private static String username; 
    private static String password; 

    @Override 
    public void run() { 
     while (true) { 
      for (MySQLDatabase database : updateList) { 
       try { 
        if (database.getConnection() == null) { 
         database.connect(); 
        } else { 
         database.ping(); 
        } 
        database.cycle(); 
       } catch (Exception ex) { 
        ex.printStackTrace(); 
       } 

       try { 
        Thread.sleep(10000); 
       } catch (Exception ex) { 
       } 
      } 
     } 
    } 

    private static void loadProperties() { 
     Properties p = new Properties(); 
     try { 
      p.load(new FileInputStream("./sql.ini")); 
      host = p.getProperty("host"); 
      database = p.getProperty("database"); 
      username = p.getProperty("username"); 
      password = p.getProperty("password"); 
     } catch (Exception ex) { 
      System.out.println("Error loading MySQL properties."); 
     } 
    } 

    public static String getHost() { 
     return host; 
    } 

    static { 
     loadProperties(); 
     updateList = new ArrayList<MySQLDatabase>(); 
     updateList.add(new MySQLDonation(host, database, username, password)); 
    } 

} 

MySQLDonation

package net.gielinor.network.sql.impl; 

import java.sql.ResultSet; 
import java.sql.SQLException; 

import net.gielinor.game.model.player.Client; 
import net.gielinor.game.model.player.PlayerHandler; 
import net.gielinor.game.model.player.PlayerSave; 
import net.gielinor.network.sql.MySQLDatabase; 

public final class MySQLDonation extends MySQLDatabase { 

    public MySQLDonation(String host, String database, String username, String password) { 
     super(host, database, username, password); 
    } 

    @Override 
    public void cycle() throws SQLException { 
     ResultSet results = query("SELECT * FROM `gieli436_purchases`.`donations`"); 
     if (results == null) { 
      return; 
     } 
     while (results.next()) { 
      String username = results.getString("username").replace("_", " "); 
      System.out.println("name=" + username); 
      Client client = (Client) PlayerHandler.getPlayer(username.toLowerCase()); 
      System.out.println(client == null); 
      if (client != null && !client.disconnected) { 
       int creditamount = results.getInt("creditamount"); 
       if (creditamount <= 0) { 
        continue; 
       } 
       handleDonation(client, creditamount); 
       query(String.format("DELETE FROM `gieli436_purchases`.`donations` WHERE `donations`.`username`='%s' LIMIT 1", client.playerName.replaceAll(" ", "_"))); 
      } 
     } 
    } 

    @Override 
    public void ping() { 
     super.ping("donations", "username"); 
    } 

    private void handleDonation(Client client, int creditamount) throws SQLException { 
     client.credits = (client.credits + creditamount); 
     client.sendMessage("Thank you for your purchase. You have received " + creditamount + " store credits."); 
     PlayerSave.save(client); 
    } 

} 

例外がここで起こる:

:MySQLDonation内のwhileループと実際のスタックトレースである。この210
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:794) 
    at com.mysql.jdbc.ResultSetImpl.next(ResultSetImpl.java:7077) 
    at net.gielinor.network.sql.impl.MySQLDonation.cycle(Unknown Source) 
    at net.gielinor.network.sql.MySQLHandler.run(Unknown Source) 

この情報では、このになります。メッセージは表示され、ゲーム内では何が繰り返されますが、ユーザーは決してクエリから削除されないので、無限の報酬が与えられます。それ以上の情報が必要な場合は、お気軽にお問い合わせください。

+1

クエリ機能は何をしますか? ResultSetをクローズしている可能性があります。 – shazin

+0

パブリックResultSetのクエリ(文字列クエリ)は、SQLExceptionをスローする{ if(query.toLowerCase()。startsWith( "select")){ return statement.executeQuery(query); } else { statement.executeUpdate(query); } return null; } "クエリ"があります。文字列が選択と等しい場合、クエリが実行されます。それ以外の場合は、指定されたクエリに更新を送信します。 – rmcmk

+0

MySQLDonation.pingは抽象的なsuper.pingを呼び出します!このコードはコンパイルされません... – Aubin

答えて

16

Deleteクエリを実行すると、Selectクエリで使用されたのと同じStatementを使用します。同じStatementで再実行すると、前のResultSetが閉じられます。

これを避けるには、クエリを実行するたびに新しいStatementを作成する必要があります。したがって、MySQLDatabaseクラスのconnect()メソッドからstatement = connection.createStatement();を削除し、そのクラスのstatementをすべてconnection.createStatement()に置き換えます。また、プライベート変数statementを完全に削除することもできます。

詳しくはhereをご覧ください。

+0

申し訳ありませんが、それは理にかなっています。問題を引き起こした「削除」クエリか、またはテーブルへの最初のクエリですか? – rmcmk

+0

その削除クエリ。ループから取り除くと、コードは機能しますが、ロジックが間違っていると思います。 –

+0

どのように?もう少し詳しく説明してください。さて、@ galuano1、私は_statement_インスタンスと "クエリ"メソッドを削除し、すべてのクエリに独自のステートメントを与えました。 – rmcmk

2

diffに同じ文オブジェクトを使用すると、このエラーが発生することがあります。タイプ

check文objectsssss;

関連する問題