准备好的语句生命周期和c3p0

时间:2016-02-02 14:44:11

标签: java mysql database-connection prepared-statement c3p0

我有一个关于使用预准备语句和连接池(如c3p0)的问题。我有一个运行的脚本,每秒一次与我的mysql数据库交互,无限制。每个交互都执行准备好的语句。根据文档,在数据库交互之前和之后应该打开和关闭连接。我的理解是Connection对象实际上并没有被销毁,而是被添加回池中。由于预处理语句是依赖于连接的,因此如何在不从每次从池中获取连接时重建它们时使用预准备语句 - 或者我只是在池接收到连接后重建语句并依赖池来通过缓存有效地做到这一点?

1 个答案:

答案 0 :(得分:3)

如果您的池实现了JDBC透明语句缓存(如c3p0那样),那么您只需使用普通的JDBC PreparedStatement API并为您处理重用的缓存语句。

在内部会发生的情况是,当您在某些Connection上调用conn.prepareStatement(...)时,将使用包含Connection的标识,SQL文本和请求的预准备语句的其他特征的密钥对内部哈希表执行查找。如果找到合适的PreparedStatement,那就是传递给客户端的内容。如果没有,那么prepareStatement调用将传递给Connection,并且返回的PreparedStatement将被缓存以供以后重用。

语句缓存本身有一些开销,配置起来可能很棘手。一些较新的连接池,尤其是HikariCP,只是省略了支持,认为PreparedStatements的缓存最好留给DBMS。当然,这是一个经验问题,从DBMS到DBMS会有所不同。如果您使用Statement缓存,关键点是您需要允许

[num_frequently_used_prepared_statments] * [num_connections]

要缓存的不同语句。考虑到JDBC标准全局maxStatements配置属性定义了全局限制,即使PreparedStatements按连接作用范围,这也很难理解。

更好的是,如果使用c3p0,则只设置(非标准)maxStatementsPerConnection属性。应将其设置为至少应用程序经常使用的PreparedStatements数。您不必担心将打开多少个连接,因为maxStatementsPerConnection的每个连接的范围都与语句本身相同。

我希望这有帮助!