On dit que c'est une bonne habitude de fermer toutes les ressources JDBC après utilisation. Mais si j'ai le code suivant, est-il nécessaire de fermer l'ensemble de résultats et l'instruction?
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 elle laisse certaines ressources en cours d'utilisation.
Réponses:
Ce que vous avez fait est une pratique parfaite et très bonne.
La raison pour laquelle je dis sa bonne pratique ... Par exemple, si pour une raison quelconque vous utilisez un type de pool de base de données "primitif" et que vous appelez
connection.close()
, la connexion sera renvoyée au pool et leResultSet
/Statement
ne sera jamais fermé, puis vous va rencontrer de nombreux nouveaux problèmes!Vous ne pouvez donc pas toujours compter sur
connection.close()
le nettoyage.J'espère que ça aide :)
la source
Java 1.7 nous simplifie la vie grâce à l' instruction try-with-resources .
Cette syntaxe est assez brève et élégante. Et
connection
sera en effet fermé même s'ilstatement
n'a pas pu être créé.la source
;
)Depuis les javadocs :
Cependant, les javadocs ne sont pas très clairs quant à savoir si
Statement
etResultSet
sont fermés lorsque vous fermez le sous-jacentConnection
. Ils déclarent simplement que la fermeture d'une connexion:À mon avis, fermez toujours explicitement
ResultSets
,Statements
etConnections
lorsque vous avez terminé avec eux car la mise en œuvre declose
peut varier entre les pilotes de base de données.Vous pouvez vous sauver beaucoup de code de plaque chauffante en utilisant des méthodes telles que
closeQuietly
dans DBUtils d'Apache.la source
J'utilise maintenant Oracle avec Java. Voici mon point de vue:
Vous devez fermer
ResultSet
etStatement
explicitement, car Oracle a précédemment rencontré des problèmes pour garder les curseurs ouverts même après la fermeture de la connexion. Si vous ne fermez pas leResultSet
(curseur), une erreur comme le nombre maximal de curseurs ouverts dépassés sera générée .Je pense que vous pouvez rencontrer le même problème avec d'autres bases de données que vous utilisez.
Voici le didacticiel Fermer ResultSet une fois terminé :
la source
Si vous voulez du code plus compact, je suggère d'utiliser Apache Commons DbUtils . Dans ce cas:
la source
La méthode correcte et sûre pour fermer les ressources associées à JDBC ceci (tiré de Comment fermer correctement les ressources JDBC - à chaque fois ):
la source
Peu importe si
Connection
est groupable ou non. Même la connexion groupable doit être nettoyée avant de retourner à la piscine."Nettoyer" signifie généralement la fermeture des ensembles de résultats et l'annulation de toutes les transactions en attente mais pas la fermeture de la connexion. Sinon, la mise en commun perd son sens.
la source
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
Connection
fermera tous lesStatement
s créés par la connexion. La fermeture de toutStatement
fermera tous lesResultSet
s créés par celaStatement
. Peu importe siConnection
est groupable ou non. Même la connexion groupable doit être nettoyée avant de retourner à la piscine.Bien sûr, vous pourriez avoir de longues boucles imbriquées sur la
Connection
création de nombreuses instructions, puis les fermer est approprié. Je ne ferme presque jamaisResultSet
, semble excessif lors de la fermetureStatement
ou lesConnection
fermera.la source
J'ai créé la méthode suivante pour créer une doublure réutilisable:
J'utilise ce code dans une classe parent qui est héritée de toutes mes classes qui envoient des requêtes DB. Je peux utiliser l'Oneliner sur toutes les requêtes, même si je n'ai pas de resultSet. La méthode s'occupe de fermer le ResultSet, Statement, Connection dans le bon ordre. Voici à quoi ressemble finalement mon bloc.
la source
Pour autant que je m'en souvienne, dans le JDBC actuel, les ensembles de résultats et les instructions implémentent l'interface AutoCloseable. Cela signifie qu'ils sont fermés automatiquement lorsqu'ils sont détruits ou hors de portée.
la source
close
est appelé à la fin d'une instruction try-with-resources. Voir docs.oracle.com/javase/tutorial/essential/exceptions/… et docs.oracle.com/javase/8/docs/api/java/lang/AutoCloseable.html .Quelques fonctions pratiques:
la source
Avec Java 6, je pense qu'il vaut mieux vérifier qu'il est fermé ou non avant de fermer (par exemple si un pooleur de connexions expulse la connexion dans un autre thread) - par exemple un problème de réseau - l'état de la déclaration et du jeu de résultats peut être fermé. (ça n'arrive pas souvent, mais j'ai eu ce problème avec Oracle et DBCP). Mon modèle est pour cela (dans l'ancienne syntaxe Java):
En théorie, il n'est pas parfait à 100% car entre la vérification de l'état de fermeture et la fermeture elle-même, il y a un peu de place pour le changement d'état. Dans le pire des cas, vous recevrez un avertissement sous peu. - mais il est moindre que la possibilité de changement d'état dans les requêtes à long terme. Nous utilisons ce modèle en production avec une charge «moyenne» (150 utilisateurs simultanés) et nous n'avons eu aucun problème avec lui - alors ne voyez jamais ce message d'avertissement.
la source
isClosed()
tests, car la fermeture de ceux qui sont déjà fermés est un no-op. Ce qui élimine le problème de la fenêtre de synchronisation. Ce qui serait également éliminé en créant les variables localesConnection, Statement
etResultSet
.