Hibernate prepareConnection / preparedStatement问题

时间:2018-02-19 05:31:13

标签: java hibernate jpa c3p0

在我们的项目中,我们将Spring更新为4.3.14.RELEASE,将Hibernate更新为4.3.11.Final,因为我们已经开始看到两个警告:

  1.   

    WARN JDBC重置的连接与最初准备的连接不一样 - 请确保使用连接释放模式ON_CLOSE(默认值)并运行Hibernate 4.2+(或将HibernateJpaDialect的prepareConnection标志切换为false

    • 解决方法是将发布模式切换为ON_CLOSE,这是我们不想要的 - 当我们的应用程序负载很重时,它会停止释放连接并且应用程序卡住了。这适用于释放模式AFTER_TRANSACTION。
    • 如果忽略此错误,该消息并未说明会发生什么。谷歌搜索没有显示任何明确的
    • 如果我们将prepareConnection标记切换为false会怎样?我试图在Hibernate配置中找到这样的标志,但无法找到它。
  2.   

    GooGooStatementCache:441 - Multiply prepared statement!

    • 此警告是否与之前的警告有关?这是我们应该担心的吗?
  3. 编辑:我将Hibernate更新为5.2.13.Final

4 个答案:

答案 0 :(得分:4)

以下是多重准备语句的解释(来自GooGooStatementCache source):

  

此连接已经准备了相同的声明,   并且其他实例尚未关闭,因此语句池   必须准备第二个PreparedStatement对象而不是重用   先前缓存的Statement。新的Statement将被缓存,以防万一   您经常需要多份本声明。

在英语中,这意味着PreparedStatementConnection检出同一PreparedStatement之前从Connection签出了Thread。这是不寻常的。只有一个客户端Connection通常一次与PreparedStatement进行交互,如果需要多次,通常会重复使用相同的close()(重置其参数)。可能发生这种情况的最可能原因是因为应用程序没有PreparedStatement它打开的Connection,依靠c3p0在close()-ing签入时清除它们。

在任何情况下,它都不是正确性问题,c3p0会很好地处理这个案子。但它可能反映了可以稍微清理的代码(在使用后立即通过PreparedStatement PreparedStatement或重新使用它们)在内存和资源使用方面更有效。如果您使用的是当前版本(0.9.5.2),c3p0应该会向您显示有问题的Connection的文本。

我不知道为什么你会看到Spring / Hibernate警告。 c3p0已签出Connection是代理,但其身份在其客户端可见生命周期内不会发生变化。看一下source,在获得与Session相关联的Session时会有一些反思和间接,然后将其与已检出的Connection进行比较。即使在使用ConnectionSession时,某些内容也可能导致{{1}}刷新其关联的{{1}}?我希望我能得到更多帮助,但我不确定发生了什么。

答案 1 :(得分:2)

通过使用Tomcat JDBC Pool,我遇到了同样的问题。

问题在春季出现,因为他们在351行进行了相等性检查 HibernateJpaDialect

比较是在连接池(在您的情况下为Tomcat Pool或c3p0)代理的连接上完成的。

如果您设置ON_CLOSE(休眠中的旧行为),则仅在重置/关闭会话时才会关闭连接,这不会引起任何问题,但可能会改变性能,特别是如果客户端将Hibernate会话保持打开一段时间。 / p>

如果设置(默认)AFTER_TRANSACTION,则在事务完成之后和会话关闭之前释放连接。第301行JdbcCoordinatorImpl

通常,此方法resetSessionState()检查是否两次关闭连接 line 349 if (this.preparedCon != null && this.session.isConnected())

出现问题是因为在第一个发行版(事务之后)期间(由连接池代理的)连接已更改,并且未满足相等性导致警告消息。 此警告消息是误报

答案 2 :(得分:0)

您可以尝试使用属性hibernate.connection.handling_mode

hibernate.connection.handling_mode=DELAYED_ACQUISITION_AND_HOLD

如果您使用的是JTA

hibernate.connection.handling_mode=DELAYED_ACQUISITION_AND_RELEASE_AFTER_TRANSACTION

hibernate.connection.handling_mode=DELAYED_ACQUISITION_AND_RELEASE_AFTER_STATEMENT

请参阅此springframework javadoc部分 setPrepareConnection

答案 3 :(得分:0)

通过以下设置禁用org.springframework.orm.jpa.support.OpenEntityManagerInViewInterceptor

spring:
  jpa:
    open-in-view: false
    hibernate:
      connection:
        release_mode: on_close # default mode, you can remove this line