2013-04-22 14 views
5

Ho lavorato a questo per quasi un giorno e mezzo e non riesco a risolvere questo errore. Non so perché il ResultSet viene chiuso. Forse qualcuno di voi può aiutarmi.Eccezione JDBC Java MySQL: "Operazione non consentita dopo ResultSet chiuso"

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); 
    } 

} 

L'eccezione si verifica qui: nel ciclo while all'interno MySQLDonation e StackTrace reale è questo:

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) 

Con queste informazioni lasciatemi dire che questo fa lavoro, ottengo il mio messaggio e ciò che non in-game, ma ripete, come l'utente non viene mai rimosso dalla query in modo che dà loro infinite ricompense. Se hai bisogno di ulteriori informazioni non esitare a chiedere.

+1

Cosa fa la funzione di query. Potrebbe chiudere il ResultSet. – shazin

+0

query ResultSet pubblica (query stringa) genera SQLException { if (query.toLowerCase(). StartsWith ("select")) { return statement.executeQuery (query); } else { statement.executeUpdate (query); } return null; } C'è "query", se la stringa è uguale a select eseguiamo la query; altrimenti inviamo un aggiornamento alla query specificata. – rmcmk

+0

MySQLDonation.ping chiama super.ping che è astratto! Questo codice non viene compilato ... – Aubin

risposta

16

Quando si esegue la query Delete, si utilizza lo stesso Statement utilizzato nella query Select. Quando si esegue nuovamente lo stesso Statement, viene chiuso il precedente ResultSet.

Per evitare ciò, è necessario creare un nuovo Statement ogni volta che si esegue una query. Quindi rimuovere statement = connection.createStatement(); dal metodo connect() nella classe MySQLDatabase e sostituire tutto il statement in quella classe a connection.createStatement(). Puoi anche scegliere di cancellare la variabile privata statement del tutto.

Ulteriori informazioni a riguardo here.

+0

Va bene, questo ha più senso. Sarebbe la mia query di "cancellazione" a causare il problema o la query iniziale alla tabella? – rmcmk

+0

è la query di eliminazione. Se lo fai fuori dal giro, il tuo codice funzionerebbe, ma credo che la logica sarà completamente sbagliata. –

+0

Come mai? La mente ti spiega un po 'di più in profondità?Va bene, @ galuano1, ho rimosso l'istanza _statement_ e il metodo "query" e ho dato a ciascuna query la propria istruzione. – rmcmk

2

questo errore si verifica quando si utilizza lo stesso oggetto istruzione per diff. tipi

assegno dichiarazione objectsss;

Problemi correlati