Java 方法完成后PostgreSQL关闭连接

Java 方法完成后PostgreSQL关闭连接,java,postgresql,spring-mvc,spring-boot,Java,Postgresql,Spring Mvc,Spring Boot,我注意到我最近无法访问我的PostgreSQL。我允许的20个连接都用光了。我不明白为什么,因为我什么也没有打开。似乎即使在电脑关闭或其他情况下,事情仍然是开放的。我正在使用远程真实数据库在本地工作,并且当我使用相同的数据库推送实时数据库时 下面是一个示例方法,我想知道使用后是否需要关闭它 @RequestMapping("/users") public String users(Model model) { try { Connection connection = g

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

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

@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();}
}
@RequestMapping(“/users”)
公共字符串用户(模型){
试一试{
Connection=getConnection();
语句stmt=connection.createStatement();
字符串sql;
sql=“从cuser中选择id、第一个、最后一个、电子邮件、公司、城市”;
结果集rs=stmt.executeQuery(sql);
StringBuffer sb=新的StringBuffer();
列表用户=新建ArrayList();
while(rs.next()){
int id=rs.getInt(“id”);
String first=rs.getString(“first”);
字符串last=rs.getString(“last”);
String email=rs.getString(“电子邮件”);
字符串公司=rs.getString(“公司”);
String city=rs.getString(“城市”);
添加(新用户(id、第一个、最后一个、电子邮件、公司、城市));
}
model.addAttribute(“用户”,用户);
返回“用户”;
}catch(异常e){返回e.toString();}
}
在此方法结束时,我应该如何关闭连接

非常感谢所有获得时间回答的人(假设您直接使用JDBC来打开自己的连接)

这个怎么样


好的,这里有几个问题

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

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

try(Connection=getConnection();
语句stmt=connection.createStatement();
结果集rs=stmt.executeQuery(sql)){
StringBuffer sb=新的StringBuffer();
列表用户=新建ArrayList();
while(rs.next()){
int id=rs.getInt(“id”);
String first=rs.getString(“first”);
字符串last=rs.getString(“last”);
String email=rs.getString(“电子邮件”);
字符串公司=rs.getString(“公司”);
String city=rs.getString(“城市”);
添加(新用户(id、第一个、最后一个、电子邮件、公司、城市));
}
model.addAttribute(“用户”,用户);
返回“用户”;
}

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


顺便说一句,请确保使用连接池;让请求使用池中的现有连接要比创建新连接快得多。当您从池中获取连接时,它会包装在一个对象中,该对象会将连接返回到池并进行清理(如回滚任何正在进行的事务)你应该使用一个连接池,如果你使用的是Spring Boot,像JdbcTemplate或JPA这样的东西可以让你的生活更轻松。是的,使用Spring Boot、JDBC和PostgreSQLOk,我必须把你的答案读几遍才能理解。听起来不错。我会按照你的解释实现这些非常感谢你抽出时间来帮助我。很好received@NathanHughes,你完全正确…我只是省略了
finally
块中的异常句柄,以使示例更简单…我将编辑它。谢谢!
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) { ... }
     }
}
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";
}