web-dev-qa-db-fra.com

Les résultats et les instructions JDBC doivent-ils être fermés séparément alors que la connexion est fermée par la suite?

Il est recommandé de fermer toutes les ressources JDBC après utilisation. Mais si j'ai le code suivant, est-il nécessaire de fermer le Resultset et le Statement?

Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try {
    conn = // Retrieve connection
    stmt = conn.prepareStatement(// Some SQL);
    rs = stmt.executeQuery();
} catch(Exception e) {
    // Error Handling
} finally {
    try { if (rs != null) rs.close(); } catch (Exception e) {};
    try { if (stmt != null) stmt.close(); } catch (Exception e) {};
    try { if (conn != null) conn.close(); } catch (Exception e) {};
}

La question est de savoir si la fermeture de la connexion fait le travail ou si certaines ressources sont utilisées.

233
Zeemee

Ce que vous avez fait est parfait et très bon entraînement.

La raison pour laquelle je dis sa bonne pratique ... Par exemple, si pour une raison quelconque vous utilisez un pooling de base de données de type "primitif" et que vous appelez connection.close(), la connexion sera renvoyée au pool et la variable ResultSet/Statement ne sera jamais fermé et vous rencontrerez alors de nombreux nouveaux problèmes!

Donc, vous ne pouvez pas toujours compter sur connection.close() pour nettoyer.

J'espère que ça aide :)

185
Paul

Java 1.7 facilite grandement notre vie grâce à l’énoncé déclaration d’essai avec ressources .

try (Connection connection = dataSource.getConnection();
    Statement statement = connection.createStatement()) {
    try (ResultSet resultSet = statement.executeQuery("some query")) {
        // Do stuff with the result set.
    }
    try (ResultSet resultSet = statement.executeQuery("some query")) {
        // Do more stuff with the second result set.
    }
}

Cette syntaxe est assez brève et élégante. Et connection sera en effet fermé même lorsque le statement ne pourra pas être créé.

111

De la javadocs :

Lorsqu'un objet Statement est fermé, son objet ResultSet actuel, s'il en existe un, est également fermé.

Toutefois, les javadocs ne précisent pas clairement si les variables Statement et ResultSet sont fermées lorsque vous fermez le Connection sous-jacent. Ils déclarent simplement que la fermeture d'une connexion:

Libère immédiatement la base de données et les ressources JDBC de cet objet Connection au lieu d'attendre leur libération automatique.

À mon avis, fermez toujours explicitement ResultSets, Statements et Connections lorsque vous avez terminé, car la mise en oeuvre de close peut varier entre les pilotes de base de données.

Vous pouvez économiser beaucoup de code de chaudière en utilisant des méthodes telles que closeQuietly in DBUtils de Apache.

67
dogbane

J'utilise maintenant Oracle avec Java. Voici mon point de vue:

Vous devez fermer explicitement ResultSet et Statement car Oracle rencontrait auparavant des problèmes pour garder les curseurs ouverts même après la fermeture de la connexion. Si vous ne fermez pas le ResultSet (curseur), une erreur du type maximum sera dépassée .

Je pense que vous pouvez rencontrer le même problème avec d'autres bases de données que vous utilisez.

Voici le tutoriel Fermer ResultSet à la fin :

Fermez ResultSet lorsque vous avez terminé

Fermez l'objet ResultSet dès que vous avez fini de travailler avec l'objet ResultSet alors que l'objet Statement ferme implicitement l'objet ResultSet, la fermeture de ResultSet donne explicitement une chance garbage collector pour récupérer la mémoire le plus tôt possible car l'objet ResultSet peut occuper beaucoup de mémoire en fonction de la requête.

ResultSet.close();

35
user467871

Si vous voulez un code plus compact, je suggère d'utiliser Apache Commons DbUtils . Dans ce cas:

Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try {
    conn = // Retrieve connection
    stmt = conn.prepareStatement(// Some SQL);
    rs = stmt.executeQuery();
} catch(Exception e) {
    // Error Handling
} finally {
    DbUtils.closeQuietly(rs);
    DbUtils.closeQuietly(stmt);
    DbUtils.closeQuietly(conn);
}
6
baron5

Peu importe si Connection est groupable ou non. Même la connexion poolable doit être nettoyée avant de retourner à la piscine.

"Nettoyer" signifie généralement la fermeture des résultats et l'annulation des transactions en attente, mais pas la fermeture de la connexion, sinon la mise en commun perd sa signification.

3
Mad Calm

La méthode correcte et sûre pour fermer les ressources associées à JDBC ceci (extraite de Comment fermer correctement les ressources JDBC - À chaque fois ):

Connection connection = dataSource.getConnection();
try {
    Statement statement = connection.createStatement();

    try {
        ResultSet resultSet = statement.executeQuery("some query");

        try {
            // Do stuff with the result set.
        } finally {
            resultSet.close();
        }
    } finally {
        statement.close();
    }
} finally {
    connection.close();
}
3

Quelques fonctions pratiques:

public static void silentCloseResultSets(Statement st) {
    try {
        while (!(!st.getMoreResults() && (st.getUpdateCount() == -1))) {}
    } catch (SQLException ignore) {}
}
public static void silentCloseResultSets(Statement ...statements) {
    for (Statement st: statements) silentCloseResultSets(st);
}
0
Mad Calm

Non, vous n'êtes pas obligé de fermer quoi que ce soit MAIS la connexion. Selon les spécifications JDBC, la fermeture de tout objet supérieur fermera automatiquement les objets inférieurs. La fermeture de Connection ferme toutes les Statements que la connexion a créées. La fermeture de tout Statement ferme tous les ResultSets créés par ce Statement. Peu importe si Connection est groupable ou non. Même la connexion poolable doit être nettoyée avant de retourner à la piscine.

Bien sûr, vous pourriez avoir de longues boucles imbriquées sur la Connection créant de nombreuses instructions, puis leur fermeture est appropriée. Je ne ferme presque jamais ResultSet bien que cela semble excessif lorsque vous fermez Statement ou Connection FERME.

0
Enerccio