Hibernate启动非常缓慢

28

由于某种原因,我的Hibernate应用程序启动非常缓慢(长达2分钟)。我一直在考虑c3p0配置可能存在问题(相关问题),但是研究日志显示,在与服务器建立连接后就没有任何活动。此外,使用Hibernate的内置轮询功能也显示出相同的结果。

这是来自日志的片段:

20:06:51,248 DEBUG BasicResourcePool:422 - decremented pending_acquires: 0
20:06:51,248 DEBUG BasicResourcePool:1644 - trace com.mchange.v2.resourcepool.BasicResourcePool@1acaf0ed [managed: 3, unused: 2, excluded: 0] (e.g. com.mchange.v2.c3p0.impl.NewPooledConnection@5f873eb2)
20:06:51,248 DEBUG BasicResourcePool:1644 - trace com.mchange.v2.resourcepool.BasicResourcePool@1acaf0ed [managed: 3, unused: 2, excluded: 0] (e.g. com.mchange.v2.c3p0.impl.NewPooledConnection@5f873eb2)
20:06:51,273 DEBUG JdbcServicesImpl:121 - Database ->
       name : PostgreSQL
    version : 9.1.6
      major : 9
      minor : 1
20:06:51,274 DEBUG JdbcServicesImpl:127 - Driver ->
       name : PostgreSQL Native Driver
    version : PostgreSQL 9.2 JDBC4 (build 1002)
      major : 9
      minor : 2
20:06:51,274 DEBUG JdbcServicesImpl:133 - JDBC version : 4.0 ##### HANGS FOR 2 MINUTES  ON THIS LINE #####
20:08:14,727  INFO Dialect:123 - HHH000400: Using dialect: org.hibernate.dialect.PostgreSQLDialect
20:08:14,736  INFO LobCreatorBuilder:120 - HHH000424: Disabling contextual LOB creation as createClob() method threw error : java.lang.reflect.InvocationTargetException
20:08:14,736 DEBUG GooGooStatementCache:297 - checkinAll(): com.mchange.v2.c3p0.stmt.GlobalMaxOnlyStatementCache stats -- total size: 0; checked out: 0; num connections: 0; num keys: 0
20:08:14,736 DEBUG GooGooStatementCache:297 - checkinAll(): com.mchange.v2.c3p0.stmt.GlobalMaxOnlyStatementCache stats -- total size: 0; checked out: 0; num connections: 0; num keys: 0
20:08:14,883 DEBUG BasicResourcePool:1644 - trace com.mchange.v2.resourcepool.BasicResourcePool@1acaf0ed [managed: 3, unused: 2, excluded: 0] (e.g. com.mchange.v2.c3p0.impl.NewPooledConnection@5f873eb2)
20:08:14,883 DEBUG BasicResourcePool:1644 - trace com.mchange.v2.resourcepool.BasicResourcePool@1acaf0ed [managed: 3, unused: 2, excluded: 0] (e.g. com.mchange.v2.c3p0.impl.NewPooledConnection@5f873eb2)
20:08:14,883 DEBUG GooGooStatementCache:297 - checkinAll(): com.mchange.v2.c3p0.stmt.GlobalMaxOnlyStatementCache stats -- total size: 0; checked out: 0; num connections: 0; num keys: 0

(请留意 #comment#。)

我也尝试了一个较旧的Postgres JDBC驱动程序,但完全没有运气。

连接到本地数据库非常顺利。连接立即建立,我可以查询数据库。这个远程数据库是Heroku开发实例。我也尝试了另一个远程实例。结果相同。

我已经无法想到可以检查什么来摆脱这个烦恼。任何帮助将不胜感激。

也许我的 hibernate.cfg.xml 对你有所帮助:

http://www.hibernate.org/dtd/hibernate-

configuration-3.0.dtd">
<hibernate-configuration>
    <session-factory>
        <property name="connection.driver_class">org.postgresql.Driver</property>
        <property name="connection.url"/>
        <property name="connection.default_schema"/>
        <property name="connection.username"/>
        <property name="connection.password"/> 

        <property name="dialect">org.hibernate.dialect.PostgreSQLDialect</property>
            <property name="cache.provider_class">org.hibernate.cache.internal.NoCacheProvider</property>
        <property name="current_session_context_class">thread</property>            
        <property name="hibernate.c3p0.acquire_increment">3</property>
        <property name="hibernate.c3p0.min_size">3</property>
        <property name="hibernate.c3p0.max_size">10</property>
        <property name="hibernate.c3p0.timeout">300</property>
        <property name="hibernate.c3p0.max_statements">50</property>
        <property name="hibernate.c3p0.idle_test_period">3000</property>
        <property name="hibernate.c3p0.acquireRetryDelay">500</property>

        <property name="show_sql">true</property>
        <property name="format_sql">false</property>

        <property name="hbm2ddl.auto">validate</property>

        <mapping class="core.entities.Exam" />
        <mapping class="core.entities.Examination" />
        ...
    </session-factory>
</hibernate-configuration>

编辑:我尝试通过日志和剖析寻找延迟的原因,但是一直没有成功。(我在这个领域并不那么高级。)最后,我尝试了“试错法”,将我的数据库更改为远程MySQL实例以检查是否出现任何差异。结果发现,连接几乎立即建立。


尝试使用性能分析器,否则你只是在猜测为什么它运行得如此缓慢。 - Robin
只是一个猜想,但你可能需要检查一下你的网络,可能是DNS的问题?尝试使用服务器的IP地址而不是服务器名称。听起来有点像在等待超时。 - Joshua Martell
是的,这听起来像是网络问题。 - demaniak
6个回答

47

这看起来确实是答案。不幸的是,我现在无法检查它。不知道如果我将其标记为答案是否可以让人们朝着这个方向前进。这个问题似乎仍然引起了很多关注。 - bentrm
1
我建议采纳这个答案,因为它在类似的情况下对我起作用了。 - Oswaldo
2
这将把我的启动时间从40秒减少到14秒。将节省大量时间。 - Will
2
在 hibernate.cfg.xml 文件中:<property name="hibernate.temp.use_jdbc_metadata_defaults">false</property> - Lorenzo Lerate

16

对于Postgres,将以下内容加入应用程序配置:

spring.jpa.database-platform = org.hibernate.dialect.PostgreSQLDialect
spring.jpa.properties.hibernate.temp.use_jdbc_metadata_defaults=false

如果没有确定方言,则第一行是必需的。

结果

之前:

09:10:19.637 [main] INFO  o.h.annotations.common.Version - HCANN000001: Hibernate Commons Annotations {4.0.5.Final}
09:14:17.159 [main] INFO  org.hibernate.dialect.Dialect - HHH000400: Using dialect: org.hibernate.dialect.PostgreSQL9Dialect

约4分钟

之后:

09:40:10.930 [main] INFO  o.h.annotations.common.Version - HCANN000001: Hibernate Commons Annotations {4.0.5.Final}
09:40:11.043 [main] INFO  org.hibernate.dialect.Dialect - HHH000400: Using dialect: org.hibernate.dialect.PostgreSQLDialect

约1分钟


2
PostgreSQLDialect已被弃用:https://docs.jboss.org/hibernate/orm/5.0/javadocs/org/hibernate/dialect/PostgreSQLDialect.html - Frans

3

启动缓慢可能是由于以下配置引起的:

<property name="hbm2ddl.auto">update</property>

这个配置的作用是在Hibernate启动时,检查实体类与ddl是否匹配,并做出相应的操作,例如“创建”、“更新”。但是这会耗费很多时间。

因此解决方案是注释掉这个配置,这样Hibernate就可以在不进行验证的情况下启动。


2
我在将数据库从10g升级到11时遇到了问题。 我在代码中发现了以下设置:
    hibernateProperties.setProperty("hibernate.dialect","org.hibernate.dialect.Oracle10gDialect");

并且必须按照以下方式更改方言:

    hibernateProperties.setProperty("hibernate.dialect", "org.hibernate.dialect.Oracle11gDialect");

有一次这个对我不再起作用,我必须更改以下内容,以避免被卡在“HHH000400: Using dialect: org.hibernate.dialect.Oracle10gDialect”:

hibernateProperties.setProperty("hibernate.temp.use_jdbc_metadata_defaults", "false");

此外,我还需要注释以下内容,以免出现“HV000001:Hibernate Validator 6.1.5.Final”卡顿的情况:

        // hibernateProperties.setProperty("hibernate.hbm2ddl.auto", "validate");

1
你正在使用哪种容器?c3p0应该安装在容器中,例如Tomcat。如果你正在运行单元测试,请不要使用连接池。如果你将其放入tomcat中,可以使用Resource标签进行连接,然后使用JNDI连接。这是最好的方法。

0
如果应用程序异常缓慢,那么可能是因为您的应用程序中有锁定或资源阻塞。无论如何,下载VisualVM(JDK包括jconsole,它的简化版本)并检查线程正在做什么,它们被卡在哪里(threaddump),如果这些信息不能提供任何快速答案,则打开分析器。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接