Es ist eine gute Angewohnheit, alle JDBC-Ressourcen nach der Verwendung zu schließen. Muss ich die Ergebnismenge und die Anweisung schließen, wenn ich den folgenden Code habe?
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 belegt sind.
Was Sie getan haben, ist perfekt und sehr gute Praxis.
Der Grund, warum ich es für eine gute Praxis halte ... Wenn Sie beispielsweise aus irgendeinem Grund einen "primitiven" Typ von Datenbankpooling verwenden und connection.close()
aufrufen, wird die Verbindung an den Pool zurückgegeben und der ResultSet
/Statement
wird niemals geschlossen, und dann treten viele neue Probleme auf!
Sie können sich also nicht immer darauf verlassen, dass connection.close()
aufräumt.
Ich hoffe das hilft :)
Java 1.7 erleichtert uns das Leben dank der try-with-resources-Anweisung .
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.
}
}
Diese Syntax ist recht kurz und elegant. Und connection
wird in der Tat geschlossen, auch wenn das statement
nicht erstellt werden konnte.
Aus dem javadocs :
Wenn ein
Statement
-Objekt geschlossen wird, wird auch sein aktuellesResultSet
-Objekt geschlossen, sofern eines vorhanden ist.
Die Javadocs wissen jedoch nicht genau, ob Statement
und ResultSet
geschlossen sind, wenn Sie das zugrunde liegende Connection
schließen. Sie geben einfach an, dass eine Verbindung geschlossen wird:
Gibt die Datenbank und die JDBC-Ressourcen dieses
Connection
Objekts sofort frei, anstatt darauf zu warten, dass sie automatisch freigegeben werden.
Nach meiner Meinung sollten Sie ResultSets
, Statements
und Connections
immer explizit schließen, wenn Sie damit fertig sind, da die Implementierung von close
zwischen den Datenbanktreibern variieren kann.
Sie können sich mit Methoden wie closeQuietly
in DBUtils von Apache eine Menge Code sparen.
Ich benutze jetzt Oracle mit Java. Hier meine Sichtweise:
Sie sollten ResultSet
und Statement
explizit schließen, da Oracle zuvor Probleme damit hatte, die Cursor auch nach dem Schließen der Verbindung offen zu halten. Wenn Sie den ResultSet
(Cursor) nicht schließen, wird ein Fehler wie ausgelöst. Die maximale Anzahl offener Cursor wurde überschritten .
Ich denke, Sie könnten das gleiche Problem mit anderen von Ihnen verwendeten Datenbanken haben.
Hier ist das Tutorial Schließen Sie ResultSet, wenn Sie fertig sind :
Schließen Sie ResultSet, wenn Sie fertig sind
Schließen Sie das Objekt
ResultSet
, sobald Sie mit dem ObjektResultSet
fertig sind, obwohl das ObjektStatement
das ObjektResultSet
beim Schließen implizit schließt, und schließen SieResultSet
gibt explizit die Möglichkeit, den Garbage Collector so früh wie möglich zum Speichern zu bewegen, da das ObjektResultSet
je nach Abfrage möglicherweise viel Speicher belegt.
ResultSet.close();
Wenn Sie kompakter Code möchten, empfehle ich die Verwendung von Apache Commons DbUtils . In diesem Fall:
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);
}
Es spielt keine Rolle, ob Connection
poolfähig ist oder nicht. Auch poolfähige Verbindungen müssen vor der Rückkehr in den Pool gereinigt werden.
"Bereinigen" bedeutet normalerweise, Ergebnismengen zu schließen und alle ausstehenden Transaktionen zurückzusetzen, aber die Verbindung nicht zu schließen, da andernfalls das Pooling den Sinn verliert.
Die korrekte und sichere Methode zum Schließen der mit JDBC verknüpften Ressourcen ist diese (entnommen aus So schließen Sie JDBC-Ressourcen ordnungsgemäß - jedes Mal ):
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();
}
Einige Komfortfunktionen:
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);
}
Nein, Sie müssen nichts schließen, ABER die Verbindung. Gemäß den JDBC-Spezifikationen werden niedrigere Objekte automatisch geschlossen, wenn ein höheres Objekt geschlossen wird. Wenn Sie Connection
schließen, werden alle Statement
s geschlossen, die von dieser Verbindung erstellt wurden. Wenn Sie ein Statement
schließen, werden alle ResultSet
s geschlossen, die von diesem Statement
erstellt wurden. Es spielt keine Rolle, ob Connection
poolfähig ist oder nicht. Auch poolfähige Verbindungen müssen vor der Rückkehr in den Pool gereinigt werden.
Natürlich könnten Sie lange verschachtelte Schleifen auf dem Connection
haben, die viele Anweisungen erzeugen, dann ist es angebracht, sie zu schließen. Ich schließe ResultSet
so gut wie nie, scheint aber übermäßig zu sein, wenn ich Statement
oder Connection
schließe.