【问题标题】:How often should Connection, Statement and ResultSet be closed in JDBC?JDBC 中 Connection、Statement 和 ResultSet 应该多久关闭一次?
【发布时间】:2011-08-01 22:42:25
【问题描述】:

是否需要在每次查询后关闭并在每次查询开始时进行初始化?

【问题讨论】:

    标签: java jdbc


    【解决方案1】:

    总是。您需要在尽可能短的范围内获取并关闭它们,以避免资源泄漏、事务问题和耗尽的连接池。不这样做会导致数据库迟早会耗尽资源,从而导致“连接过多”等异常。

    正常的 JDBC 习惯用法如下,所有资源都在同一个 try-with-resources 块中打开

    public List<Entity> list() throws SQLException {
        List<Entity> entities = new ArrayList<Entity>();
    
        try (
            Connection connection = database.getConnection();
            PreparedStatement statement = connection.prepareStatement(SQL_LIST);
            ResultSet resultSet = statement.executeQuery();
        ) {
            while (resultSet.next()) {
                entities.add(map(resultSet));
            }
        }
    
        return entities;
    }
    

    或者当您还没有使用 Java 7 时:

    public List<Entity> list() throws SQLException {
        List<Entity> entities = new ArrayList<Entity>();
        Connection connection = null;
        PreparedStatement statement = null;
        ResultSet resultSet = null;
    
        try {
            connection = database.getConnection();
            statement = connection.prepareStatement(SQL_LIST);
            resultSet = statement.executeQuery();
    
            while (resultSet.next()) {
                entities.add(map(resultSet));
            }
        } finally {
            if (resultSet != null) try { resultSet.close(); } catch (SQLException logOrIgnore) {}
            if (statement != null) try { statement.close(); } catch (SQLException logOrIgnore) {}
            if (connection != null) try { connection.close(); } catch (SQLException logOrIgnore) {}
        }
    
        return entities;
    }
    

    使用PreparedStatement 将使您受益于语句的数据库缓存(在正确使用时可防止 SQL 注入)。获取和关闭连接是最昂贵的任务,但连接池就是为此而发明的。如果您想重复使用相同的语句来进行批量插入/更新,那么您可以使用批处理。

    另见:

    【讨论】:

    • 为什么不为每个应用程序使用一个连接?
    • @Alex78191 这在“另见”链接中得到了回答。我通常从不张贴它们来装饰。他们通常会回答在阅读答案时弹出的新问题。全部点击,你会学到很多东西。
    • 不可以回收连接吗?
    • @inf3rno:是的。这就是所谓的“连接池”。编写 JDBC 代码的方式绝对不应该改变。您只需要确保database.getConnection() 返回一个池连接。如果您正在开发基于 Servlet 的应用程序,请从这里开始:stackoverflow.com/q/2299469
    【解决方案2】:

    由于您不想要上一个查询的结果,因此您当然需要初始化 ResultSet。

    如果再次需要,可以保留该语句,特别是应保留 PreparedStatements - 它们可以在数据库第一次运行时预编译,从而节省一些时间:

    "SELECT foo FROM bar WHERE a = ?" 
    

    如果只是参数改变,当然。

    【讨论】:

    • 如果你关闭一个连接——当你希望能够运行你的应用程序比数据库的默认连接超时时间更长时这是强制性的,例如 webapplications——那么所有打开的语句也将被关闭,因此你不能让它们保持打开状态(并且肯定不会分配为类/实例变量或其他东西)。
    • 如果。我没有阅读有关 web 应用程序和超时的内容。但是,在大多数情况下,您是对的。但在单用户机器上,数据库也有其优势。
    猜你喜欢
    • 2010-11-05
    • 2014-05-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-21
    • 2011-01-04
    • 1970-01-01
    相关资源
    最近更新 更多