Es wird als gute Angewohnheit bezeichnet, alle JDBC-Ressourcen nach der Verwendung zu schließen. Aber wenn ich den folgenden Code habe, ist es notwendig, die Ergebnismenge und die Anweisung zu schließen?
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) {};
}
Die Frage ist, ob das Schließen der Verbindung den Job erledigt oder ob einige Ressourcen verwendet werden.
Antworten:
Was Sie getan haben, ist perfekt und sehr gute Praxis.
Der Grund, warum ich es als gute Praxis bezeichne ... Wenn Sie beispielsweise aus irgendeinem Grund einen "primitiven" Datenbankpooling-Typ verwenden und aufrufen
connection.close()
, wird die Verbindung zum Pool zurückgegeben und dasResultSet
/Statement
wird niemals geschlossen und dann Sie wird auf viele verschiedene neue Probleme stoßen!Sie können sich also nicht immer darauf verlassen
connection.close()
, aufzuräumen.Ich hoffe das hilft :)
quelle
Java 1.7 erleichtert unser Leben dank der Anweisung "Try-with-Resources" erheblich .
Diese Syntax ist sehr kurz und elegant. Und
connection
wird in der Tat geschlossen, auch wenn dasstatement
nicht erstellt werden konnte.quelle
;
Aus den Javadocs :
Die Javadocs sind sich jedoch nicht ganz sicher, ob die
Statement
undResultSet
geschlossen sind, wenn Sie den Basiswert schließenConnection
. Sie geben einfach an, dass das Schließen einer Verbindung:Meiner Meinung nach immer explizit schließen
ResultSets
,Statements
undConnections
wenn Sie damit fertig sind, kann die Implementierung vonclose
zwischen Datenbanktreibern variieren.Mit Methoden wie
closeQuietly
in DBUtils von Apache können Sie sich viel Kesselplattencode sparen .quelle
Ich benutze jetzt Oracle mit Java. Hier mein Standpunkt:
Sie sollten schließen
ResultSet
undStatement
explizit, da Oracle zuvor Probleme hat, die Cursor auch nach dem Schließen der Verbindung offen zu halten. Wenn Sie denResultSet
(Cursor) nicht schließen , wird ein Fehler wie " Maximale Anzahl offener Cursor überschritten" ausgegeben .Ich denke, dass Sie bei anderen von Ihnen verwendeten Datenbanken möglicherweise auf dasselbe Problem stoßen.
Hier ist das Tutorial Schließen Sie ResultSet, wenn Sie fertig sind :
quelle
Wenn Sie kompakteren Code wünschen, empfehle ich die Verwendung von Apache Commons DbUtils . In diesem Fall:
quelle
Die richtige und sichere Methode zum Schließen der mit JDBC verknüpften Ressourcen (siehe So schließen Sie JDBC-Ressourcen jedes Mal richtig ):
quelle
Es spielt keine Rolle, ob
Connection
Pooling möglich ist oder nicht. Sogar die Pool-Verbindung muss gereinigt werden, bevor Sie zum Pool zurückkehren."Bereinigen" bedeutet normalerweise, Ergebnismengen zu schließen und ausstehende Transaktionen zurückzusetzen, aber die Verbindung nicht zu schließen. Andernfalls verliert das Pooling seinen Sinn.
quelle
Nein, Sie müssen nichts schließen, ABER die Verbindung. Gemäß den JDBC-Spezifikationen werden beim Schließen eines höheren Objekts automatisch niedrigere Objekte geschlossen. Durch das Schließen
Connection
werden alle vonStatement
der Verbindung erstellten s geschlossen. Wenn Sie eineStatement
schließen, werden alleResultSet
s geschlossen, die dadurch erstellt wurdenStatement
. Es spielt keine Rolle, obConnection
Pooling möglich ist oder nicht. Sogar die Pool-Verbindung muss gereinigt werden, bevor Sie zum Pool zurückkehren.Natürlich haben Sie möglicherweise lange verschachtelte Schleifen
Connection
, um viele Anweisungen zu erstellen. Dann ist es angebracht, diese zu schließen. Ich schließe fast nieResultSet
, scheine beim Schließen übertriebenStatement
oderConnection
werde sie schließen.quelle
Ich habe die folgende Methode erstellt, um wiederverwendbaren One Liner zu erstellen:
Ich verwende diesen Code in einer übergeordneten Klasse, die an alle meine Klassen geerbt wurde, die DB-Abfragen senden. Ich kann den Oneliner für alle Abfragen verwenden, auch wenn ich kein resultSet habe. Die Methode sorgt dafür, dass ResultSet, Statement, Connection in der richtigen Reihenfolge geschlossen werden. So sieht mein Endblock aus.
quelle
Soweit ich mich erinnere, implementieren Resultsets und Anweisungen im aktuellen JDBC die AutoCloseable-Schnittstelle. Das heißt, sie werden automatisch geschlossen, wenn sie zerstört werden oder den Geltungsbereich verlassen.
quelle
close
am Ende einer Try-with-Resources-Anweisung aufgerufen wird. Siehe docs.oracle.com/javase/tutorial/essential/exceptions/… und docs.oracle.com/javase/8/docs/api/java/lang/AutoCloseable.html .Einige Komfortfunktionen:
quelle
Mit Java 6 Form ist es meiner Meinung nach besser zu überprüfen, ob es geschlossen ist oder nicht, bevor es geschlossen wird (zum Beispiel, wenn ein Verbindungspooler die Verbindung in einem anderen Thread entfernt) - zum Beispiel ein Netzwerkproblem -, dass die Anweisung und der Ergebnismengenstatus geschlossen werden können. (Es kommt nicht oft vor, aber ich hatte dieses Problem mit Oracle und DBCP). Mein Muster dafür ist (in älterer Java-Syntax):
Theoretisch ist es nicht 100% perfekt, da zwischen der Überprüfung des Schließzustands und dem Schließen selbst ein kleiner Raum für die Zustandsänderung besteht. Im schlimmsten Fall erhalten Sie lange eine Warnung. - aber es ist weniger als die Möglichkeit einer Statusänderung bei langfristigen Abfragen. Wir verwenden dieses Muster in der Produktion mit einer "durchschnittlichen" Last (150 gleichzeitige Benutzer) und hatten kein Problem damit - sehen Sie diese Warnmeldung also nie.
quelle
isClosed()
Tests nicht, da das Schließen von bereits geschlossenen Tests ein No-Op ist. Dadurch wird das Problem mit dem Zeitfenster beseitigt. Was auch durch die Erstellung derConnection, Statement
undResultSet
lokalen Variablen beseitigt würde .