【问题标题】:PostgreSQL Close connection after method has finishedPostgreSQL 方法完成后关闭连接
【发布时间】:2016-11-27 11:34:54
【问题描述】:

我注意到我最近无法访问我的 PostgreSQL。我允许的所有 20 个连接都用完了。我不明白为什么,因为我什么都没有打开。似乎即使在 PC 关闭或其他情况下,事情仍然保持打开状态。我正在使用在本地工作的远程真实数据库,并且当我使用相同的数据库实时推送它时。

这是一个示例方法,我想知道使用后是否需要关闭

@RequestMapping("/users")
public String users(Model model) {
    try {
        Connection connection = getConnection();
        Statement stmt = connection.createStatement();
        String sql;
        sql = "SELECT id, first, last, email, company, city FROM cuser";
        ResultSet rs = stmt.executeQuery(sql);
        StringBuffer sb = new StringBuffer();
        List users = new ArrayList<>();
        while (rs.next()) {
            int id = rs.getInt("id");
            String first = rs.getString("first");
            String last = rs.getString("last");
            String email = rs.getString("email");
            String company = rs.getString("company");
            String city = rs.getString("city");
            users.add(new User(id,first, last, email, company, city));
        }
        model.addAttribute("users", users);
        return "user";
    }catch(Exception e) {return e.toString();}
}

我应该如何在这个方法结束时关闭连接

非常感谢有时间回答的人

【问题讨论】:

  • 您应该使用连接池,如果您使用的是 Spring Boot,JdbcTemplate 或 JPA 之类的东西可以让您的生活更轻松。
  • 是的,使用 Spring Boot、JDBC 和 PostgreSQL

标签: java postgresql spring-mvc spring-boot


【解决方案1】:

这个怎么样(这里假设你直接使用 JDBC 来打开你自己的连接)...

Connection conn = null;
ResultSet rs    = null;
try {
    conn = getConnection();
    ...
} catch (Exception ex) {
    ...
} finally {
     if (rs != null) { 
         try { rs.close(); } catch (Exception ex) { ... }
     }
     if (conn != null) {
         try { conn.close(); } catch (Exception ex) { ... }
     }
}

【讨论】:

  • @NathanHughes,你是绝对正确的......我只是省略了 finally 块中的异常句柄,以使示例更简单......我会编辑它。谢谢!
【解决方案2】:

好的,这里有几个问题。

首先是数据库连接最终确实需要超时。有时,由于某些报告需要永远或类似的问题,超时会延长到一些荒谬的事情,但这是一种反模式。您需要将连接超时,以便当出现诸如连接搁浅之类的错误时,数据库可以从中恢复。

其次,完成后始终关闭连接。这里最简单的方法是使用 try-with-resources,这将确保您的资源以正确的顺序关闭,而不会出现异常屏蔽(关闭引发的异常会导致 try 块中引发先前的异常)迷路,这很糟糕,因为这意味着您不知道代码失败的原因):

try (Connection connection = getConnection(); 
    Statement stmt = connection.createStatement();
    ResultSet rs = stmt.executeQuery(sql)) {
    StringBuffer sb = new StringBuffer();
    List users = new ArrayList<>();
    while (rs.next()) {
        int id = rs.getInt("id");
        String first = rs.getString("first");
        String last = rs.getString("last");
        String email = rs.getString("email");
        String company = rs.getString("company");
        String city = rs.getString("city");
        users.add(new User(id,first, last, email, company, city));
    }
    model.addAttribute("users", users);
    return "user";
}

第三,考虑在你的 Spring Boot 应用程序中使用更多的 Spring。您的控制器中包含数据访问权限,因此您没有关注点分离,并且您没有利用 Spring 提供的任何功能,如 JDBC 模板、资源关闭、命名参数、数据异常转换(以便异常你从 jdbc 调用返回是有意义的),或者事务处理(让你在同一个事务中进行多个 DAO 调用)。有关 spring-jdbc 文档,请参阅 this link

顺便说一句,请确保使用连接池;让请求使用池中的现有连接比建立新连接要快得多。当您从池中获得连接时,它会包装在一个对象中,该对象将连接返回到池并在您调用 close 时进行清理(如回滚任何正在进行的事务)。

【讨论】:

  • 好的,我将不得不阅读您的答案几次才能掌握它。听起来不错。正如您所解释的那样,我将全部实施。非常感谢您抽出时间来帮助我。深受好评
猜你喜欢
  • 2013-04-22
  • 2020-07-13
  • 2022-07-27
  • 2012-02-07
  • 1970-01-01
  • 1970-01-01
  • 2016-06-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多