我正在使用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();
});
}
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。
在使用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驱动通常对此有很好的处理)。