用Java关闭数据库连接

ona*_*000 113 java database-connection

我有点困惑,我正在阅读以下http://en.wikipedia.org/wiki/Java_Database_Connectivity

Connection conn = DriverManager.getConnection(
     "jdbc:somejdbcvendor:other data needed by some jdbc vendor",
     "myLogin",
     "myPassword" );

Statement stmt = conn.createStatement();
try {
    stmt.executeUpdate( "INSERT INTO MyTable( name ) VALUES ( 'my name' ) " );
} finally {
    //It's important to close the statement when you are done with it
    stmt.close();
}
Run Code Online (Sandbox Code Playgroud)

你不需要关闭连接吗?如果没有发生conn.close(),会发生什么?

我有一个私人网络应用程序,我正在维护,目前没有关闭任何一种形式,但重要的是真正的stmt one,conn one或者两者兼而有之?

该网站间歇性地停止,但服务器一直说这是一个数据库连接问题,我怀疑它没有关闭,但我不知道哪个关闭.

Pas*_*ent 184

完成使用后Connection,需要通过调用其close()方法显式关闭它,以释放连接可能持有的任何其他数据库资源(游标,句柄等).

实际上,Java中的安全模式是在你完成它们时关闭你的ResultSet,, StatementConnection(以这个顺序)finally,就像这样:

Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;

try {
    // Do stuff
    ...

} catch (SQLException ex) {
    // Exception handling stuff
    ...
} finally {
    if (rs != null) {
        try {
            rs.close();
        } catch (SQLException e) { /* ignored */}
    }
    if (ps != null) {
        try {
            ps.close();
        } catch (SQLException e) { /* ignored */}
    }
    if (conn != null) {
        try {
            conn.close();
        } catch (SQLException e) { /* ignored */}
    }
}
Run Code Online (Sandbox Code Playgroud)

finally块可以略微改进(以避免空检查):

} finally {
    try { rs.close(); } catch (Exception e) { /* ignored */ }
    try { ps.close(); } catch (Exception e) { /* ignored */ }
    try { conn.close(); } catch (Exception e) { /* ignored */ }
}
Run Code Online (Sandbox Code Playgroud)

但是,这仍然是非常冗长,所以你通常最终使用一个帮助器类来关闭null安全帮助器方法中的对象,并且finally块变成这样的:

} finally {
    DbUtils.closeQuietly(rs);
    DbUtils.closeQuietly(ps);
    DbUtils.closeQuietly(conn);
}
Run Code Online (Sandbox Code Playgroud)

实际上,Apache Commons DbUtils有一个DbUtils正是这样做的类,因此不需要编写自己的类.

  • @Pascal Thivent:实际上我们不需要关闭所有这些."核心Java第二卷 - 高级特性"一书写道:如果语句有一个打开的结果集,`Statement`对象的`close`方法会自动关闭相关的`ResultSet`.类似地,`Connection`类的`close`方法关闭`Connection`的所有`Statements`. (11认同)
  • @Majid:除非它是一个汇集的连接.然后这些陈述就会泄漏掉. (11认同)
  • 非常棒的帮助,谢谢!我没有抓住或想到conn!= null语句. (3认同)
  • @BalusC:你能解释一下使用 connection.close() 方法关闭池连接时会发生什么吗 (2认同)
  • @Krnsa:通常,它会被释放回池中,而池又会在幕后担心测试/获取连接。 (2认同)

Yad*_*nan 57

使用后关闭数据库/资源​​对象总是更好.最好关闭块中的连接,结果集和语句对象finally.

在Java7之前,需要使用finally块关闭所有这些资源.如果您使用的是Java 7,那么要关闭资源,您可以执行以下操作.

try(Connection con = getConnection(url, username, password, "org.postgresql.Driver");
    Statement stmt = con.createStatement();
    ResultSet rs = stmt.executeQuery(sql);
) {

//statements
}catch(....){}
Run Code Online (Sandbox Code Playgroud)

现在,con,stmt和rs对象成为try块的一部分,java在使用后自动关闭这些资源.

希望我有所帮助.


Gri*_* A. 13

这足以关闭公正StatementConnection.无需显式关闭ResultSet对象.

Java文档说java.sql.ResultSet:

当Statement对象关闭,重新执行或用于从多个结果序列中检索下一个结果时,Statement对象会自动关闭它生成它的Statement对象.


感谢BalusC的评论:"我不会依赖它.一些JDBC驱动程序失败了."

  • 我不会依赖它.一些JDBC驱动程序失败了.例如,Oracle"超出最大开放游标数"等.只需明确关闭所有打开的资源,没有任何借口. (24认同)
  • 正如BalusC指出的那样,好的防御性编程是显式关闭连接,而不是硬性依赖特定提供者。 (2认同)

Bri*_*new 11

是.您需要关闭结果集,语句和连接.如果连接来自池,则关闭它实际上会将其发送回池以供重用.

您通常必须在一个finally{}块中执行此操作,这样如果抛出异常,您仍然有机会关闭它.

许多框架将为您处理此资源分配/解除分配问题.例如Spring的JdbcTemplate.Apache DbUtils有一些方法来关闭结果集/语句/连接,无论是否为null(并在关闭时捕获异常),这也可能有所帮助.

  • 废话,我刚刚回答了我自己的问题并试了一下,抱歉 (2认同)

Ale*_*ler 7

是的,您需要关闭Connection.否则,数据库客户端通常会保持套接字连接和其他资源处于打开状态.

  • ...直到它退出。这束缚了客户端和服务器端的各种有限资源。如果客户端做这种事情太多,它可能会给客户端本身、数据库服务甚至客户端或服务器机器上运行的其他应用程序带来问题。 (2认同)

Joe*_*Joe 5

实际上,最好使用try-with-resources块,并且在退出try块时Java将为您关闭所有连接。

您应该对实现AutoClosable的任何对象执行此操作。

try (Connection connection = getDatabaseConnection(); Statement statement = connection.createStatement()) {
    String sqlToExecute = "SELECT * FROM persons";
    try (ResultSet resultSet = statement.execute(sqlToExecute)) {
        if (resultSet.next()) {
            System.out.println(resultSet.getString("name");
        }
    }
} catch (SQLException e) {
    System.out.println("Failed to select persons.");
}
Run Code Online (Sandbox Code Playgroud)

刚刚完成了对getDatabaseConnection的调用。将其替换为使您获得JDBC SQL连接或来自池的连接的调用。