2009-11-19 6 views
0

Je compile une liste de variables de page (qui contient une liste de livres) à partir d'une base de données MYSQL en cours d'exécution. Lorsque j'essaie la deuxième itération dans la boucle while (rs.next()), je reçois une exception SQL indiquant que le ResultSet était déjà fermé. Je ne vois nulle part que ce code ferme l'objet rs.ResultSet fermeture prématurée

try { 
    stmt = con.createStatement(); 
    ResultSet rs = 
      stmt.executeQuery("SELECT pageURL," + 
        "pageName FROM pages GROUP BY pageName;"); 
    ResultSet rs2; 
    while(rs.next()) { // Where the error occurs on the second pass 
     Page tempP = new Page(rs.getString(1),rs.getString(2)); 
     rs2 = stmt.executeQuery("SELECT `books`.`itemID`,cost," + 
       "title,author,shortD,longD FROM " + 
       "books INNER JOIN pages ON " + 
       "books.itemID=pages.itemID WHERE " + 
       "pageName='" + rs.getString(2) + "';"); 
     while(rs2.next()) { 
      tempP.addBook(new Book(rs2.getInt(1), 
        rs2.getFloat(2),rs2.getString(3), 
        rs2.getString(4),rs2.getString(5), 
        rs2.getString(6))); 
     } 
     pages.addPage(tempP); 
    } 
} catch(SQLException e) { 
    System.err.print("SQLException: "); 
    System.err.println(e.getMessage()); 
} 

Voici le contenu de la table pages:

|pageName |pageURL |itemID| 
------------------------------- 
|Tech Books|./techbooks|1  | 
------------------------------- 
|Tech Books|./techbooks|2  | 
------------------------------- 
|Kids Books|./kidsbooks|3  | 
------------------------------- 
|Kids Books|./kidsbooks|4  | 
------------------------------- 
|Kids Books|./kidsbooks|5  | 
------------------------------- 

EDIT:

D'accord, il semble que ResultSet devient invalide quand je l'utilise à nouveau la déclaration. Quelqu'un at-il des suggestions pour remédier à cette situation?

+3

Votre deuxième requête comporte une menace d'injection SQL possible. Même si vous êtes sûr que c'est sûr, c'est une mauvaise forme de coder de cette façon et cela nuira également à l'optimisation de vos requêtes dans la base de données. –

+0

Je suis sûr que c'est sûr, mais que suggérez-vous pour optimiser cela? –

+1

@Kevin: utilisez un PreparedStatement avec des variables de liaison (setString) – Thilo

Répondre

4

Pour citer les javadocs pour Déclaration:

Par défaut, un seul objet ResultSet par objet Statement peut être ouvert en même temps. Par conséquent, si la lecture d'un objet ResultSet est entrelacée avec la lecture d'un autre, chacun doit avoir été généré par différents objets Statement. Toutes les méthodes d'exécution de l'interface Statement ferment implicitement l'objet ResultSet actuel d'une requête si celui-ci existe.

Créez deux instructions ou, mieux encore, utilisez PreparedStatements avec des variables liées.

+0

Merci beaucoup! –

0

Voir la documentation de ResultSet:

Un objet ResultSet est fermé automatiquement lorsque l'objet énoncé qui a généré, il est fermé, ré-exécutée, ou utilisé pour récupérer le prochain résultat d'une séquence de résultats multiples.