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.
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 :)
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éé.
De la javadocs :
Lorsqu'un objet
Statement
est fermé, son objetResultSet
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.
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'objetResultSet
alors que l'objetStatement
ferme implicitement l'objetResultSet
, la fermeture deResultSet
donne explicitement une chance garbage collector pour récupérer la mémoire le plus tôt possible car l'objetResultSet
peut occuper beaucoup de mémoire en fonction de la requête.
ResultSet.close();
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);
}
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.
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();
}
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);
}
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 Statement
s que la connexion a créées. La fermeture de tout Statement
ferme tous les ResultSet
s 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.