我们有一个春季项目,我们使用
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 NOT 解决此问题
编辑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 似乎转向休眠4.3.1.FINAL DOES 解决了这个问题。没有得到关于准备日志的任何警告。和内存分析器不会显示db连接上的任何泄漏。
问题
连接hibernate
和c3p0
以及spring
的最佳方式是什么?使用hibernate-c3p0
包或将c3p0
包添加到pom中?
答案 0 :(得分:5)
所以,我无法解释为什么你在较新版本的Hibernate中看到更多这样的内容,但是你看到的消息意味着你的应用程序正在尝试准备一个已经准备好并缓存的PreparedStatement数据库连接非常相同。但是,无法使用缓存的Statement,因为它仍在使用中,尚未进行close()编辑。因此,正在编写同一份声明的新副本。 (如果您经常同时重复使用Statement,缓存将保留两个副本。)
理论上,有些情况可能正是您打算做的。例如,当遍历递归结构展平为数据库表时,您可以重复使用具有不同参数的相同查询来向下钻取级别,同时顶级查询保持打开状态。
但实际上,这种情况很少见。通常,如果您收到此消息,则可能意味着您的应用程序未及时关闭()语句。根据您的描述,听起来您可能也有连接泄漏,但是您没有报告通常的结果,当池到达maxPoolSize
时应用程序挂起。 (你没有报告过很多关于你的c3p0配置;也许你已经设置maxPoolSize
非常大,并且在池耗尽之前你会遇到内存问题。)
你可能会尝试一些事情:
1)检查是否有连接泄漏。见here
2)简化问题:通过关闭语句缓存并比较行为,查看问题是否仅限于语句缓存。将c3p0参数maxStatements
和maxStatementsPerConnection
都设置为零。