开发者社区 问答 正文

数据库连接池上的try-with资源是否每次都会关闭连接?

我正在使用HikariDataSource来管理到我的Postgres DB的连接池。

我正在尝试使用一种资源来从HikariDataSource获取连接,我想了解以下内容:

每次连接是否真的关闭?

如果是,那么以这种方式使用准备好的语句没有优势吗?

将准备好的语句与连接池一起使用的最佳实践是什么?

这是我的连接代码:

public <T> CompletableFuture<T> withConnection(FunctionThatThrowsChecedException<Connection, T> action) {
        return CompletableFuture.supplyAsync(() -> {
            try (Connection connection = ds.getConnection()) {
                return action.apply(connection);
            } catch (SQLException | IOException e) {
                throw new RuntimeException("error while getting collection", e);
            }
        }, workerThreads);
    }

下面是使用预准备语句执行查询的一些示例:

public CompletableFuture<Integer> delete(String batchId) {
        return postgresProvider.withConnection(connection -> {
            PreparedStatement ps = connection.prepareStatement(DELETE_QUERY);

            ps.setString(1, batchId);
            return ps.executeUpdate();
        });
    }

展开
收起
垚tutu 2019-11-28 18:38:03 879 分享 版权
阿里云 AI 助理回答

在使用HikariDataSource时,每次通过ds.getConnection()获取的连接,在你示例代码中的try-with-resources块结束时(即执行完action.apply(connection)之后),确实会被自动关闭。但是这里的“关闭”是一个智能操作:对于连接池而言,它实际上并不是真的断开与数据库的物理连接,而是将这个连接归还给连接池,以便后续请求可以重用这个连接。这样可以显著减少建立新数据库连接的开销,提高应用程序性能。

关于准备好的语句(PreparedStatement)的优势,即便是在使用连接池的情况下,依然非常显著: 1. 预编译:数据库服务器只需要解析和优化SQL语句一次,然后存储执行计划,后续执行时直接复用,减少了重复解析的成本。 2. 安全性:通过参数化查询,可以有效防止SQL注入攻击,因为参数值不会被解释为SQL的一部分。 3. 性能:特别是对于频繁执行的相同SQL但参数不同的情况,预编译的执行计划重用能带来性能提升。

结合连接池使用PreparedStatement的最佳实践包括: - 及时关闭PreparedStatement:虽然在你的withConnection方法中,连接会自动归还给池子,但PreparedStatement对象本身也应该在不再需要时关闭,以释放可能关联的资源。通常这可以通过将其放在更内层的try-with-resources块中实现,尽管在Java 8及以后版本中,如果PreparedStatement是通过Connection创建的且没有其他资源需要管理,JDBC驱动通常会在连接关闭时自动处理这些资源。 - 重用PreparedStatement:在逻辑上连续或频繁执行相似SQL操作时,考虑是否可以设计模式来重用同一个PreparedStatement对象,进一步减少数据库的编译负担。 - 参数绑定:始终使用参数占位符(?)并正确绑定变量,避免字符串拼接来构造SQL,确保安全性和性能。

综上所述,你的代码片段已经很好地展示了如何结合连接池和PreparedStatement使用,只需注意在必要时显式关闭PreparedStatement(虽然现代JDBC驱动通常对此有很好的处理)。

有帮助
无帮助
AI 助理回答生成答案可能存在不准确,仅供参考
0 条回答
写回答
取消 提交回答