spring - Hibernate 4.3-final 是否会导致 GooGooStatementCache 乘以准备好的语句?

标签 spring hibernate spring-data c3p0

我们有一个使用的 spring 项目
Spring + Spring Data + Hibernate + c3p0
一切正常,直到最后几个版本。我们开始看到很多INFO GooGooStatementCache:441在我们的日志中。此外,在我们的服务器端出现一些内存问题之后。我们开始对我们的 Java 内存堆进行一些分析。似乎在我们得到很多 INFO GooGooStatementCache:441 的所有版本中都是如此我们有严重的内存泄漏。 com.mysql.jdbc.JDBC4Connection不会免费。因此,我们有许多连接保持打开状态。

我们怀疑从 hibernate 3.6.3.Final 的变化( hibernate-entitymanager ) 到 hibernate 3.0.Final导致这些问题。

有其他人经历过这样的事情吗?

谢谢,

阿隆

编辑:
之间切换:

    <!-- <jpa.version>2.0.0</jpa.version> -->
    <hibernate.version>4.3.0-Final</hibernate.version>
    <hibernate.entitymanager.version>4.3.0.Final</hibernate.entitymanager.version>

    <!-- <hibernate.jpa-api.version>2.0-cr-1</hibernate.jpa-api.version> -->

到:
    <jpa.version>2.0.0</jpa.version>
    <hibernate.version>3.5.6-Final</hibernate.version>

和这个:
    <dependency>
        <groupId>org.hibernate.java-persistence</groupId>
        <artifactId>jpa-api</artifactId>
        <version>${hibernate.jpa-api.version}</version>
        <scope>compile</scope>
    </dependency>

    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-entitymanager</artifactId>
        <version>${hibernate.entitymanager.version}</version>
        <scope>compile</scope>
    </dependency>

到:
    <!-- Hibernate and JPA -->
    <!-- seems like we get jppa api from hibernate-entitymanager -->
    <!-- <dependency> -->
    <!-- <groupId>org.hibernate.java-persistence</groupId> -->
    <!-- <artifactId>jpa-api</artifactId> -->
    <!-- <version>${hibernate.jpa-api.version}</version> -->
    <!-- <scope>compile</scope> -->
    <!-- </dependency> -->

    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-entitymanager</artifactId>
        <version>${hibernate.entitymanager.version}</version>
        <scope>compile</scope>
    </dependency>

防止 INFO GooGooStatementCache:441 - Multiply prepared statement!问题
所以我们的设置和 hibernate 4.3.0-final 似乎存在某种问题

有任何想法吗?

编辑 2 :

更改为 4.3.1.Final 是 不是 解决了这个问题

编辑 3
感谢您的回复
我的猜测是它不适用于 c3p0和新 hibernate
这是我们设置它们的方式
<!-- Declare a datasource that has pooling capabilities-->   
<bean id="jpaDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
    destroy-method="close"
    p:driverClass="${app.jdbc.driverClassName}"
    p:jdbcUrl="${app.jdbc.url}"
    p:user="${app.jdbc.username}"
    p:password="${app.jdbc.password}"
    p:acquireIncrement="5"
    p:idleConnectionTestPeriod="60"
    p:maxPoolSize="100"
    p:maxStatements="50"
    p:minPoolSize="10" />

<!-- Declare a JPA entityManagerFactory -->
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" 
    p:persistenceXmlLocation="classpath*:META-INF/persistence.xml"
    p:persistenceUnitName="hibernatePersistenceUnit"
    p:dataSource-ref="jpaDataSource"
    p:jpaVendorAdapter-ref="hibernateVendor"/>

<!-- Specify our ORM vendor -->
<bean id="hibernateVendor" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"
            p:showSql="false"/>

<!-- Declare a transaction manager-->
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager" 
    p:entityManagerFactory-ref="entityManagerFactory"/>

这是持久性文件
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
    version="1.0">
<persistence-unit name="hibernatePersistenceUnit"
    transaction-type="RESOURCE_LOCAL">
    <properties>
        <property name="hibernate.hbm2ddl.auto" value="update"/>
        <property name="hibernate.show_sql" value=${show.sql} /> 
        <property name="hibernate.format_sql" value="true" />
        <property name="hibernate.dialect"    value="org.hibernate.dialect.MySQL5InnoDBDialect" />
    </properties>
    <mapping-file>META-INF/orm.xml</mapping-file>
</persistence-unit>
 </persistence>

编辑 4
似乎转向 hibernate 4.3.1.FINAL 解决了这个问题。不要收到有关要记录的准备语句的任何警告。并且内存分析器在数据库连接上没有显示任何泄漏。

问题
什么是最好的连接方式 hibernatec3p0spring ?使用 hibernate-c3p0打包或添加 c3p0打包到pom?

最佳答案

因此,我无法解释为什么您会在较新版本的 Hibernate 中看到更多这种情况,但是您看到的消息意味着您的应用程序正在尝试准备一个 PreparedStatement,它已经由同一个数据库准备和缓存联系。但是缓存的Statement不能使用,因为还在使用中,还没有被close()ed。因此,正在准备同一声明的新副本。 (缓存将保存两个副本,以防您经常同时重用该语句。)

从理论上讲,在某些情况下,这可能正是您打算执行的操作。例如,在遍历展平到数据库表中的递归结构时,您可能会重用具有不同参数的相同查询来向下钻取级别,同时顶级查询保持打开状态。

不过,在实践中这种情况很少见。通常,如果您收到此消息,则可能意味着您的应用程序没有及时关闭 () 语句。根据你的描述,听起来你也可能有连接泄漏,虽然你没有报告通常的结果,但当池达到 maxPoolSize 时应用程序挂起. (您没有报告太多关于您的 c3p0 配置的信息;也许您将 maxPoolSize 设置得非常大,并且在池耗尽之前遇到了内存问题。)

你可能会尝试一些事情:

1) 检查您是否有连接泄漏。见 here

2) 简化问题:通过关闭语句缓存并比较行为,查看问题是否仅限于语句缓存。设置 c3p0 参数 maxStatementsmaxStatementsPerConnection都为零。

关于spring - Hibernate 4.3-final 是否会导致 GooGooStatementCache 乘以准备好的语句?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21574541/

相关文章:

java - 如何使用@Query在JPA中获取自动生成的 key ?

java - 是否有一种方法可以解析 int 或如果无法解析则返回 0?

java - Hibernate 级联与逆向关系

java - Hibernate返回 "weird"连接

Spring 数据 : inject 2 repositories with same name but in 2 different packages

java - Cassandra Spring Data不允许我直接通过复合主键查询数据

java - 如何使用 Spring Boot 和 Maven 设置配置文件?

Spring Boot ActiveMQ

hibernate - 使用 Hibernate 在 Wildfly 上使用 JPA 创建表失败

java - 返回时间戳而不是普通对象 ID 的 Spring Data Mongo 模板