Frage

Ich habe Code-Review getan eines unserer Lieblingsprojekte und FindBugs (meist Tools wie FindBugs verwenden) markierte als fehlerhaft folgenden Code (Pseudo-Code):

Connection conn = dataSource.getConnection();

try{
    PreparedStatement stmt = conn.prepareStatement();
    //initialize the statement
    stmt.execute();
    ResultSet rs =  stmt.getResultSet();
    //get data
}finally{
    conn.close();
}

Der Fehler war, dass dieser Code nicht Ressourcen freigeben könnte. Ich fand heraus, dass die ResultSet und Statement nicht geschlossen waren, so dass ich schloss sie in guter Letzt:

finally{
    try{
        rs.close()
    }catch(SqlException se){
        //log it
    }
    try{
        stmt.close();
    }catch(SqlException se){
        //log it
    }
    conn.close();
}

Aber ich begegnete dem obigen Muster in vielen Projekten (von ganz wenigen Unternehmen), und niemand Resultsets oder Statements wurde geschlossen wird.

Haben Sie Probleme mit Resultsets und Statements nicht geschlossen wird, wenn die Verbindung geschlossen wird?

fand ich nur diese und es bezieht sich auf Oracle Probleme mit mit Resultsets zu schließen, wenn Verbindungen zu schließen (wir benutzen Oracle db, meine Korrekturen daher). java.sql.api sagt nichts in Connection.close () javadoc.

War es hilfreich?

Lösung

Ein Problem bei ONLY Schließen der Verbindung und nicht die Ergebnismenge, ist, dass, wenn Ihr Verbindungsmanagement-Code wird das Verbindungsspooling verwenden, die connection.close() nur die Verbindung wieder in dem Pool setzen würde. Darüber hinaus haben einige Datenbank einen Cursor-Ressource auf dem Server, richtig wird nicht freigegeben, wenn es nicht ausdrücklich geschlossen wird.

Andere Tipps

Ich habe Probleme mit unclosed Result in Oracle hat, obwohl die Verbindung geschlossen wurde. Der Fehler, den ich bekam, war

"ORA-01000: maximum open cursors exceeded"

So: Schließen Sie immer Ihre ResultSet

!

Sie sollten immer in der Nähe aller JDBC-Ressourcen explizit. Als Aaron und John schon sagte, wird oft eine Verbindung geschlossen wird es nur wieder in einem Pool und nicht alle JDBC-Treiber sind genau die gleiche Art und Weise umgesetzt werden.

Hier ist eine Hilfsmethode, die von einem finally-Block verwendet werden kann:

public static void closeEverything(ResultSet rs, Statement stmt,
        Connection con) {
    if (rs != null) {
        try {
            rs.close();
        } catch (SQLException e) {
        }
    }
    if (stmt != null) {
        try {
            stmt.close();
        } catch (SQLException e) {
        }
    }
    if (con != null) {
        try {
            con.close();
        } catch (SQLException e) {
        }
    }
}

Oracle geben Ihnen Fehler über offene Cursor in diesem Fall.

Nach: http: //java.sun .com / JavaSE / 6 / docs / api / java / sql / Statement.html

es sieht aus wie eine Erklärung Wiederverwendung werden alle geöffneten Resultsets schließen, und eine Erklärung schließen, gehen alle Result schließen, aber ich sehe nicht, etwas über eine Verbindung geschlossen wird jede der Ressourcen schließen sie erstellt.

All diese Details sind der JDBC-Treiber-Anbieter verlassen.

Es ist immer am sichersten alles explizit zu schließen. Wir schrieben ein util-Klasse, die alles mit try {xxx} hüllt catch (Throwable {}, so dass Sie nur nennen Utils.close (rs) und Utils.close (Anw), usw., ohne sich um Ausnahmen zu kümmern, die angeblich schließen scannen werfen .

Das ODBC-Bridge kann ein Speicherleck mit einigen ODBC-Treiber erzeugen.

Wenn Sie einen guten JDBC-Treiber verwenden, dann sollten Sie keine Probleme haben, mit dem Schließen der Verbindung. Aber es gibt zwei Probleme:

  • Haben Sie wissen, wenn Sie einen guten Fahrer haben?
  • Werden Sie andere JDBC-Treiber in der Zukunft?

Dass die beste Praxis ist alles zu schließen.

ich in einer großen J2EE Web-Umgebung arbeiten. Wir haben mehrere Datenbanken, die in einer einzigen Anfrage verbunden werden kann. Wir begannen logische Deadlocks in einigen unserer Anwendungen zu bekommen. Das Problem war, dass wie folgt:

  1. Benutzer würde anfordern Seite
  2. Server eine Verbindung zum DB 1
  3. Server Wählt auf DB 1
  4. Server "schließt" Verbindung zum DB 1
  5. Server eine Verbindung zum DB 2
  6. Deadlocked!

Dies geschah aus 2 Gründen waren wir weit höheres Verkehrsaufkommen als normal und die J2EE-Spezifikation von Standard erleben nicht wirklich Ihre Verbindung zu schließen, bis der Thread der Ausführung beendet. Also, in dem obigen Beispiel Schritt 4 eigentlich nie die Verbindung geschlossen, obwohl sie in endlich richtig geschlossen wurden.

Um dies zu beheben, Sie müssen Sie Ressourcenreferenzen in der web.xml für Ihre Datenbankverbindungen verwenden und den res-sharing-scope zu unsharable setzen müssen.

Beispiel:

<resource-ref>
    <description>My Database</description>
    <res-ref-name>jdbc/jndi/pathtodatasource</res-ref-name>
    <res-type>javax.sql.DataSource</res-type>
    <res-auth>Container</res-auth>
    <res-sharing-scope>Unshareable</res-sharing-scope>
</resource-ref>

Ich habe mit unclosed Result definitiv Probleme gesehen, und was kann es schaden sie die ganze Zeit zu schließen, nicht wahr? Die Unzuverlässigkeit des Müssens zu erinnern, dies zu tun, ist einer der besten Gründe, um Rahmenbedingungen zu bewegen, die diese Details für Sie verwalten. Es ist vielleicht nicht in der Entwicklungsumgebung machbar sein, aber ich habe großes Glück mit Spring mußte JPA-Transaktionen zu verwalten. Die unordentlichen Details Öffnen von Verbindungen, Erklärungen, Ergebnismengen, und das Schreiben zu kompliziert try / catch / finally-Blöcke (mit try / catch-Blöcke in der finally-Block! ), um sie zu schließen, wieder nur verschwindet, so dass Sie tatsächlich einige Arbeit zu erledigen. Ich würde empfehlen, diese Art einer Lösung migrieren.

In Java-Anweisungen (nicht Result) korrelieren mit Cursor in Oracle. Am besten ist es, die Ressourcen zu schließen, die Sie als unerwartetes Verhalten öffnen kann in Bezug auf die JVM und Systemressourcen auftreten.

Darüber hinaus bündelt einig JDBC-Pooling-Frameworks Statements und Verbindungen, so schließt sie nicht nicht diese Objekte als frei im Pool markieren könnten, und Performance-Probleme im Rahmen führen.

In der Regel, wenn es eine enge () oder destroy () Methode für ein Objekt, gibt es einen Grund zu nennen, und zu ignorieren es so auf eigene Gefahr erfolgt.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top