在使用 JDBC 的 DAO 类中,哪一个是处理关闭 ResultSet、PreparedStatement 和 Connection 的 try-catch 的最佳方法?

Posted

技术标签:

【中文标题】在使用 JDBC 的 DAO 类中,哪一个是处理关闭 ResultSet、PreparedStatement 和 Connection 的 try-catch 的最佳方法?【英文标题】:Which of these two is the best way to handle try-catches for closing ResultSet, PreparedStatement, and Connection in a DAO class that uses JDBC? 【发布时间】:2018-03-01 18:32:40 【问题描述】:

我正在创建一个使用 JDBC 和 mysql 的 DAO 类。我没有收到有关如何关闭标题中列出的项目的任何指示,但我读到这样做是一种好习惯。现在我认为这应该在每个 CRUD 方法中完成,但是处理异常似乎有点人为,我不确定如何实现它。

第一个例子:

public boolean update2(Dto dto) 
    assert dto != null;
    if (readById(dto.getId()).getId() == 0) 
        throw new RuntimeException("Row with this id doesn't exist");
    
    boolean flag = false;
    try 
        Connection connection = DAOFactory.createConnection();
        String sql = "SQL statement"; 
        try 
            PreparedStatement ps = connection.prepareStatement(sql);
            try 
                // Some stuff with preparedstatement
                ps.executeUpdate();
                flag = true;
             finally 
                if (ps != null) ps.close();
            
         finally 
            if (connection != null) connection.close();
        
     catch (ClassNotFoundException e) 
        e.printStackTrace();
     catch (SQLException e) 
        e.printStackTrace();
    

    return flag;

第二个例子:

public boolean update(Dto dto) 
    assert dto != null;
    if (readById(dto.getId()).getId() == 0) 
        throw new RuntimeException("Row with this id doesn't exist");
    
    boolean flag = false;
    PreparedStatement ps = null;
    Connection connection = null;
    try 
        connection = DAOFactory.createConnection();
        String sql = "SQL statement"; 
        ps = connection.prepareStatement(sql);
        // Some stuff with preparedstatement
        ps.executeUpdate();
        flag = true;
     catch (ClassNotFoundException e) 
        e.printStackTrace();
     catch (SQLException e) 
        e.printStackTrace();
     finally 
        if (ps != null) 
            try 
                ps.close();
             catch (SQLException e) 
                e.printStackTrace();
            
        
        if (connection != null) 
            try 
                connection.close();
             catch (SQLException e) 
                e.printStackTrace();
            
        
    

    return flag;

在第二个示例中,我需要重复异常处理。第一个解决方案对我来说似乎更聪明,但我不确定它是否比第二个更具可读性。

设计中是否有不仅是主观的约定?

【问题讨论】:

【参考方案1】:

假设您使用的是Java 1.7 及以上版本,您可以使用try with resources 语句来简化资源的关闭。如果资源实现了AutoClosable 接口,ConnectionPreparedStatement 就是这种情况,您可以重写代码如下:

public boolean update2(String dto) 
    assert dto != null;

    if (readById(dto.getId()).getId() == 0) 
        throw new RuntimeException("Row with this id doesn't exist");
    

    boolean flag = false;
    String sql = "SQL statement";
    try (Connection connection = DAOFactory.createConnection();
         PreparedStatement ps = connection.prepareStatement(sql)) 
        ps.executeUpdate();
        flag = true;
     catch (ClassNotFoundException e) 
        e.printStackTrace();
     catch (SQLException e) 
        e.printStackTrace();
    

    return flag;

【讨论】:

这个结构更具可读性,我不知道,非常感谢。但是,我不明白对于早于 1.7 的版本,选择权是否落在开发人员身上,或者是否有要采用的约定。 然后使用第二个选项;这是我更喜欢的,因为代码比第一个更干净。 这是一个很好的答案,但我会更积极地处理ClassNotFoundExceptionSQLException,例如将它们包装在运行时异常中,因为这些几乎总是由无法恢复的部署/编程错误(或数据/DB 问题)引起的。 @MickMnemonic 当然。我的回答是关于如何巧妙地关闭资源。我100%靠你;不应在生产环境中将异常打印到控制台。我也想提一下,但是忘记了。谢谢,很好。

以上是关于在使用 JDBC 的 DAO 类中,哪一个是处理关闭 ResultSet、PreparedStatement 和 Connection 的 try-catch 的最佳方法?的主要内容,如果未能解决你的问题,请参考以下文章

使用普通 JDBC 在 DAO 或服务层中进行事务处理

JDBC之Druid连接池的使用

Spring---- JDBC

java 关于JDBC和DAO模式使用

从 Servlet 和 JDBC 迁移到 DAO 和 Spring,建议?

JDBC—DAO