2016-12-01 3 views
0

J'ai regardé beaucoup de réponses mais malheureusement aucune réponse à ma question et je n'arrive toujours pas à comprendre pourquoi je reçois ResultSet closed.java.sql.SQLException: ResultSet fermé sur sqlite

Voici l'extrait de code try c'est en cause du problème:

 System.out.println(" System Info! @CHKMD5Files(): Found pre-existing details: "+TOTAL); 

     Statement stmMD5 = null; 
     Connection connMD5 = null; 
     ResultSet rs_MD5 = null; 
     String RESULTMD5 = null; 

     try { 
      connMD5 = DriverManager.getConnection("jdbc:sqlite:" + bkpPATH+ hostname + ".db"); 
      stmMD5 = connMD5.createStatement(); 
      connMD5.setAutoCommit(false); 

      while (ROWID <= TOTAL) { 
       rs_MD5 = stmMD5.executeQuery("SELECT md5 FROM details WHERE ROWID = '"+ROWID+"';"); 
       RESULTMD5 = rs_MD5.getString("MD5"); 
       skipBuffer.write(RESULTMD5); 
       skipBuffer.newLine(); 
       skipBuffer.flush(); 
       ROWID++; 
       } 
      System.out.println(" System Info! @CHKMD5Files(): Done with try"); 

     } catch (Exception ex) { 
      System.out.println(" System Error! @CHKMD5Files (2): " + ex); 
      System.exit(5); 
     } finally { 
      if (stmMD5 != null){ 
       stmMD5.close(); 
       System.out.println(" System Info! @CHKMD5Files (2): Closing Statement(stmMD5)"); 
      } 
      if (connMD5 != null) { 
       connMD5.close(); 
       System.out.println(" System Info! @CHKMD5Files (2): Closing Connection(connMD5)"); 
      } 
      skipBuffer.close(); 
     } 
    } 

On dirait la boucle while ne fonctionne même pas parce que si je mets la déclaration d'impression dans la boucle ne retourne rien.

+0

À quel moment obtenez-vous cette erreur? –

+0

Pourriez-vous ajouter la trace de la pile de l'erreur ?? Cela m'aiderait énormément –

+1

"On dirait que la boucle while ne fonctionne même pas, car si je mets un point d'impression dans la boucle, rien ne se passe." Cela signifie que la variable ROWID vous donne le problème. Alors mettez du code pour ça. c'est-à-dire une partie de requête qui stocke le résultat dans ROWID. –

Répondre

2

Lorsque vous souhaitez utiliser un ResultSet, vous devez d'abord appeler la méthode next pour définir le pointeur du ResultSet sur la première ligne des résultats. Comme le Javadoc du procédé indique:

Un curseur ResultSet est initialement positionné avant la première rangée; le premier appel à la méthode fait ensuite la première rangée la rangée courante; ...

Donc, si vous ne l'appelez pas, vous ne pointe pas à aucun résultat et la méthode getString (utilisée dans RESULTMD5 = rs_MD5.getString("MD5");) génère cette exception. Donc, ajoutez au moins

rs_MD5.next() 

avant d'extraire les résultats. La méthode next renvoie une valeur booléenne pour indiquer si elle peut atteindre la ligne suivante ou non. Vous pouvez donc ajouter un if -statement pour vérifier si cette valeur est true avant d'extraire une valeur de colonne, car si le next n'a pas réussi à accéder à la ligne suivante (et renvoie false), le pointeur ne sera défini sur aucune ligne valide (il existe pas à gauche) et vous obtiendrez la même erreur si vous essayez d'accéder aux résultats (voir le lien vers javadoc de next ci-dessus).

Mais malheureusement même si vous ajoutez un appel à next, vous obtiendrez la même erreur dans la deuxième itération parce que vous ne pouvez pas utiliser le même Statement -object pour exécuter différentes requêtes. Chaque objet Statement ne peut générer qu'un seul ResultSet.
Pour résoudre cela, vous devez au moins remplacer

rs_MD5 = stmMD5.executeQuery("SELECT md5 FROM details WHERE ROWID = '"+ROWID+"';"); 

avec

rs_MD5 = connMD5.createStatement().executeQuery(
     "SELECT md5 FROM details WHERE ROWID = '"+ROWID+"';" 
); 

Mais je vous suggère autrement parce que la création d'une nouvelle Statement -object prend beaucoup de temps (chacun a être compilé avant d'être exécuté). Comme la seule chose qui change à chaque itération est le ROWID ce serait une perte de temps terrible de recompiler la même chose à chaque itération. Donc, utilisez un PreparedStatement à la place. Il vous permet d'utiliser une instruction qui ne se compile qu'une seule fois et que vous pouvez réutiliser plusieurs fois en y injectant des paramètres (après compilation). Pour utiliser un PreparedStatement que vous devez faire:

Connection conn = ... //Connection to your database 
PreparedStatement ps = conn.preparedStatement("SELECT * FROM person WHERE name = ? AND age = ?"); 

//First search all persons with name "J.Baoby" and age = 5 
ps.setString(1, "J.Baoby"); 
ps.setInt(2, 5); 
ResultSet set1 = ps.executeQuery(); 
// Do something with it 
// .... 

//Now I need persons with name "Henry" and age = 25 
ps.setString(1, "Henry"); 
ps.setInt(2, 25); 
ResultSet set1 = ps.executeQuery(); 
// Do something with it 
// ... 

La façon d'injecter ces paramètres est d'utiliser une méthode setXXX avec comme premier argument l'indice (basé sur 1) du « ? » vous voulez remplacer et le deuxième argument est la valeur.Le XXX est remplacé par le type de la valeur que vous souhaitez injecter. Les types de paramètres que vous pouvez injecter étant limités, vérifiez d'abord le Java API avant d'y insérer un objet. Vous pouvez trouver plus d'informations sur PreparedStatement dans le Java API ou sur on this site (avec quelques autres exemples).

dernier, je voudrais ajouter que vous devez fermer toutes vos ressources (JDBC) (Connection, Statement, ResultSet, PreparedStatement, ...) lorsque vous êtes sûr que vous n'avez plus besoin. Les ressources que vous ne libérez pas sont des ressources gaspillées que votre JVM aurait pu affecter à autre chose. Ne pas fermer vos ressources est une mauvaise habitude et pourrait entraîner une pénalité de performance.

Bonne chance!

1

Merci beaucoup pour toutes vos réponses et pour m'avoir indiqué le PATH correct. J'ai réussi à résoudre le problème et c'était parce que le ROWID ne contenait aucune donnée au début et que cela me causait le problème.

La déclaration supplémentaire vérifier si elle est vide resulved ma question:

   while (ROWID <= TOTAL) { 
       rs_MD5 = stmMD5.executeQuery("SELECT md5 FROM details WHERE ROWID = '"+ROWID+"';"); 
       if (!rs_MD5.next()) { 
        System.out.println(" System Info! @CHKMD5Files(): No data in rowid: "+ROWID); 
        ROWID++; 
       } else { 
        RESULTMD5 = rs_MD5.getString("MD5"); 
        skipBuffer.write(RESULTMD5); 
        skipBuffer.newLine(); 
        skipBuffer.flush(); 
        ROWID++; 
        rs_MD5.close(); 
       } 
      } 
+0

Cela m'a donné un aperçu que je n'avais pas vu venir, merci –