【问题标题】:Does hibernate use PreparedStatement by defaulthibernate 是否默认使用 PreparedStatement
【发布时间】:2013-07-19 19:18:52
【问题描述】:

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

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

有人可以澄清一下吗?

【问题讨论】:

  • “总是使用PreparedStatement”并不意味着“总是缓存PreparedStatements”——它们还提供参数插值。由于您一开始就在乞求这个问题,其余的都是从这个错误的假设中得出的,没有任何意义。您当然可以查找hibernate.c3p0.max_statements 的文档。连接池可以在内部维护每个连接语句的缓存,而完全不涉及 Hibernate。不知道 c3p0 是否这样做,但他们也有文档。

标签: java performance hibernate jakarta-ee


【解决方案1】:

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

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

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

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

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

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

【讨论】:

  • 你太好了,一个简洁的解释。 PreparedStatement 是否可以通过条件或休眠中的 save/update/saveOrUpdate 来实现?
  • 我希望 Hibernate 生成的每个 SQL 语句都准备好然后执行。总之,是的。
  • 所以缓存发生在连接和池级别(通过缓存连接),但休眠没有自己的查询缓存apmblog.dynatrace.com/2009/02/16/…
  • 查询缓存又名二级缓存(一级缓存是休眠会话)缓存实体(查询结果)。这里的讨论是关于缓存准备好的语句。缓存prepared statements与执行prepared statement时产生的结果无关。
  • jdbc4根据github.com/brettwooldridge/HikariCP支持驱动级别的preparestatment
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-13
  • 2016-12-21
  • 1970-01-01
  • 1970-01-01
  • 2019-04-06
  • 2014-01-29
相关资源
最近更新 更多