8

“Hibernate 总是使用 PreparedStatement 来调用数据库”这里引用。如果是这样,那么休眠缓存编译查询在哪里,数据库驱动程序是否缓存它们。

我读到了关于 c3p0 的信息。如果hibernate默认缓存PreparedStatement,那么c3p0中的hibernate.c3p0.max_statements有什么用。如果 hibernate 默认不这样做,那么连接池对于缓存准备好的语句是强制性的。

有人可以澄清这些。

4

1 回答 1

13

缓存准备好的语句仅在特定 JDBC 连接的范围内才有意义。因此,只有当 ORM 层可以使用某种连接池时,您才能从缓存准备好的语句中获得一些东西。否则,每次创建 Hibernate Session 时都会获得一个新的“物理”JDBC 连接(通常效率不高)。没有任何连接池缓存准备好的语句仅在单个 JDBC 连接/Hibernate Session 的范围内有用。发生这种情况是因为在没有任何连接池的情况下,“物理”连接实际上已关闭并且不会被重用 - 相反,无论何时需要,总是会使用数据库驱动程序创建一个新连接。

您需要考虑的另一件事是,单个 JDBC 连接上打开的准备好的语句的数量是有限的(据我所知,该限制取决于供应商,并且因驱动程序实现而异)。因此,在池连接场景中,池实现可能需要知道在池的每个“物理”底层 JDBC 连接上可以维护多少打开的准备好的语句。可能会实施“首先关闭最少使用的准备好的语句”策略,但这纯粹是我的猜测。

我希望这有点道理。每当我提到“物理”JDBC 连接时,我指的是与数据库的实际新 TCP/IP 连接。连接池获得的连接通常会装饰/包装“物理”连接。

编辑以更直接地回答您的问题:

Hibernate 最有可能使用和缓存 PreparedStatements(这是非常基本的 JDBC 优化)。问题是这种缓存是否发生在由“物理”或池提供的 JDBC 连接创建的语句上。如果没有缓存池,PreparedStatements 只会优化在特定 Hibernate 会话范围内两次使用特定 PreparedStatement 的应用程序执行部分。对于一个池,相同的 PreparedStatement 将(有效地)用于许多恰好使用相同底层“物理”连接的 Hibernate Session 实例。

您的 hibernate 配置的属性 hibernate.c3p0.max_statements 很可能会配置 C3PO 池实例(我很确定它是为您自动创建的),并且此配置与打开准备好的语句的数量受到限制的事实有关在“物理”JDBC 连接中。

于 2013-07-20T19:29:40.780 回答