web-dev-qa-db-fra.com

Obtention de Java.sql.SQLException: opération non autorisée après la fermeture de ResultSet

Lorsque j'exécute le code suivant, j'obtiens une exception. Je pense que c'est parce que je prépare une nouvelle déclaration avec le même objet de connexion. Comment dois-je réécrire cela pour pouvoir créer une instruction préparée ET utiliser rs2? Dois-je créer un nouvel objet de connexion même si la connexion est à la même base de données?

    try 
    {
        //Get some stuff
        String name = "";
        String sql = "SELECT `name` FROM `user` WHERE `id` = " + userId + " LIMIT 1;";
        ResultSet rs = statement.executeQuery(sql);
        if(rs.next())
        {
            name = rs.getString("name");
        }

        String sql2 = "SELECT `id` FROM  `profiles` WHERE `id` =" + profId + ";";
        ResultSet rs2 = statement.executeQuery(sql2);
        String updateSql = "INSERT INTO `blah`............"; 
        PreparedStatement pst = (PreparedStatement)connection.prepareStatement(updateSql);    

        while(rs2.next()) 
        { 
            int id = rs2.getInt("id");
            int stuff = getStuff(id);

            pst.setInt(1, stuff);
            pst.addBatch();

        }

        pst.executeBatch();

    } 
    catch (Exception e) 
    {
        e.printStackTrace();
    }

private int getStuff(int id)
{

    try
    {   

            String sql = "SELECT ......;";
            ResultSet rs = statement.executeQuery(sql);

            if(rs.next())
            {
                return rs.getInt("something");

            }
            return -1;
    }//code continues
19
samxli

Le problème vient de la façon dont vous récupérez les données dans getStuff(). Chaque fois que vous visitez getStuff() vous obtenez un ResultSet frais mais vous ne le fermez pas.

Cela viole les attentes de la classe Statement (voir ici - http://docs.Oracle.com/javase/7/docs/api/Java/sql/Statement.html ) :

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'un état s'il en existe un ouvert.

Ce qui aggrave encore les choses, c'est le rs du code appelant. Il est également dérivé hors du champ statement mais il n'est pas fermé.

Conclusion: vous avez plusieurs ResultSet appartenant au même objet Statement ouverts simultanément.

28
Itay Maman

Un objet ResultSet est automatiquement fermé lorsque l'objet Statement qui l'a généré est fermé, réexécuté ou utilisé pour récupérer le résultat suivant à partir d'une séquence de plusieurs résultats.

Je suppose qu'après while(rs2.next()) vous essayez d'accéder à quelque chose de rs1. Mais il est déjà fermé depuis que vous avez réexécuté l'instruction pour en obtenir rs2. Puisque vous ne l'avez pas fermé, je pense qu'il est utilisé à nouveau ci-dessous.

9