使用JPA的Hibernate,连接时间非常缓慢

3
我有一个项目,想要使用Hibernate进行数据库访问。在应用程序中,使用了JPA API。
持久性(persistence.xml)文件如下:
<persistence 
xmlns="http://xmlns.jcp.org/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence
http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd"
version="2.1">
    <persistence-unit name="hibernate.test"
        transaction-type="RESOURCE_LOCAL">
        <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
        <properties>
            <property name="hibernate.ejb.cfgfile" value="/hibernate/hibernate.cfg.xml"/>
        </properties>
    </persistence-unit>
</persistence>

hibernate.cfg.xml文件如下:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
                                         "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
 <session-factory>
  <property name="hibernate.connection.driver_class">oracle.jdbc.OracleDriver</property>
  <property name="hibernate.connection.password">password</property>
  <property name="hibernate.connection.url">jdbc:oracle:thin:@//server:1521/DBNAME</property>
  <property name="hibernate.connection.username">username</property>
  <property name="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</property>
  <!-- <property name="hibernate.hbm2ddl.auto">verify</property>  -->
  <property name="hibernate.default_catalog">SYS_SOMETHING</property>
  <property name="hibernate.default_schema">SYS_SOMETHING</property>
 </session-factory>
</hibernate-configuration>

问题出在这个设置上,即entityManagerFactory = Persistence.createEntityManagerFactory("hibernate.test");调用需要大约25秒才能完成。
如果我直接将配置移动到persistence.xml文件中,则连接可以在1秒钟内完成。这个错误发生在Oracle和MySQL数据库中。
我可以在日志文件中看到延迟,此时没有其他活动正在进行。
525 [pool-2-thread-1] INFO org.hibernate.cfg.Environment  - HHH000021: Bytecode provider name : javassist
21668 [pool-2-thread-1] DEBUG org.hibernate.service.internal.JaxbProcessor  - cfg.xml document did not define namespaces; wrapping in custom event reader to introduce namespace information

完整日志:http://pastebin.com/4NjPpFPe 如果不使用cfg.xml,则此延迟仅约为200毫秒。
在此期间,处理器内存不会改变,CPU使用率为0%,根据Sysinternals Process Monitor的记录,交互次数为0。
我想保留这个设置,因为hibernate.cfg.xml用于反向工程和Hibernate工具。
使用的工具: java8 hibernate-4.3.8 ojdbc7 jpa-2.1
提前感谢您的任何建议。
更新:
找到解决方案,现在我很高兴!
Hibernate框架(或XML解析器,我不确定)将等待HTTP请求。
要解决问题,请替换
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
                                         "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">

使用

<!DOCTYPE hibernate-configuration SYSTEM "-//Hibernate/Hibernate Configuration DTD 3.0//EN">

服务器启动时,延迟只会发生一次吗? - Subir Kumar Sao
这是一个连接到远程数据库的桌面应用程序。 - Biró Krisztián
1
就此而言,“hibernate.cfg.xml”与JPA无关,应合并到persistence.xml中。 - Neil Stockton
@NeilStockton 我需要用于反向工程和工具的cfg.xml文件。在persistence.xml中填写相同的数据会导致重复,应该避免。Hibernate通过hibernate.ejb.cfgfile属性支持此功能。连接可以这样工作,但创建EntityManagerFactory需要不舒适地长时间。 - Biró Krisztián
1
@kucing_terbang 非常感谢您的时间。我刚刚有时间去做了那件事。该过程在HTTP请求中挂起。更改XML DOCTYPE将解决问题。我会更新问题并提供解决方案。 - Biró Krisztián
显示剩余3条评论
3个回答

2

我找到了解决方案,现在我很开心!

Hibernate框架(或者XML解析器,我不确定)会等待HTTP请求。

为了解决这个问题,请替换:

<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
                                         "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">

使用

<!DOCTYPE hibernate-configuration SYSTEM "hibernate-configuration-3.0.dtd">

编辑:已更改“with”行,这将在发布模式和反向工程中使用正确的dtd文件(如果不指定实际文件,则无法使用reveng)。


很高兴在你的情况下解决了。但是,这只是一种解决方法,因为您跳过了XML模式的内部验证。我认为这不是一个真正的解决方案,也许您应该向Hibernate问题跟踪器提交错误报告? - MWiesner
请不要将此答案标记为解决方案,因为它只是一个权宜之计。 - MWiesner
@MWiesner 更新了我的答案,现在应该是有效的。Eclipse 也能识别它。似乎 Hibernate 尝试访问在线的 DTD,但它在代理服务器后面。如果我跳过它,包中的 DTD 将被使用。 - Biró Krisztián
好的,看起来合理,但我无法确认,因为我没有彻底测试过。 - MWiesner

1
这个问题可能与一个属性有关,该属性调节Hibernate的内部行为,以处理第一次尝试创建连接时的JDBC元数据。
尝试添加此属性。
"hibernate.temp.use_jdbc_metadata_defaults"

将以下内容添加到您的 hibernate.cfg.xml 中。在 PostgreSQL 环境中,这对我解决了类似的问题,使得“瘫痪”的启动恢复正常。默认情况下(即未显式定义),此属性设置为true,将通过 JDBC 完全加载数据库的所有元数据(在某些情况下可能会很慢...)。
然后应如下使用 hibernate.cfg.xml 文件。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
                                         "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
 <session-factory>
  <property name="hibernate.connection.driver_class">oracle.jdbc.OracleDriver</property>
  <property name="hibernate.connection.password">password</property>
  <property name="hibernate.connection.url">jdbc:oracle:thin:@//server:1521/DBNAME</property>
  <property name="hibernate.connection.username">username</property>
  <property name="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</property>
  <!-- <property name="hibernate.hbm2ddl.auto">verify</property>  -->
  <property name="hibernate.default_catalog">SYS_SOMETHING</property>
  <property name="hibernate.default_schema">SYS_SOMETHING</property>
  <property name="hibernate.temp.use_jdbc_metadata_defaults">false</property>
 </session-factory>
</hibernate-configuration>

遗憾的是,这对速度没有(明显)影响。 - Biró Krisztián
@BiróKrisztián 我同意。已经有解决方案了吗? - mjs

0

或者你可以直接从JAR文件中加载DTD:

<!DOCTYPE hibernate-mapping PUBLIC 
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 
        "classpath://org/hibernate/hibernate-mapping-3.0.dtd">

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