从Hibernate 3迁移到4会降低启动速度

我们正在尝试将我们的项目从hibernate 3迁移到hibernate 4.一切都运行良好,但问题是启动。

我们不使用JPA,我们使用直接hibernate与xml文件和映射文件。

    com.informix.jdbc.IfxDriver jdbc:informix-sqli://xxx:xxx/xxx:INFORMIXSERVER=xxx xxx xxx org.hibernate.dialect.InformixDialect true false dev.xml   

generated.mappingFile属性是一个自己的属性。 在启动时,将加载该文件(dev.xml)。 这个文件看起来像这样:

       ...        

我们减少了这篇文章中的映射数量。 我们目前有超过500个映射

使用hibernate 3 ,加载所有映射需要2秒钟 。 使用hibernate 4需要2分钟

这是来自hibernate 3.2.GA的日志文件:

  07:36:21,293 INFO [HibernateManager ] | Verwende Mapping-Collection Datei : /com/cargosoft/csedi/data/mappings_dev.xml 07:36:21,347 INFO [HibernateManager ] | Adding this resource to hibernate now : com/cargosoft/csedi/data/aart/Aart_DEV.hbm.xml 07:36:21,443 INFO [HibernateManager ] | Adding this resource to hibernate now : com/cargosoft/csedi/data/abteilung/Abteilung_DEV.hbm.xml 07:36:21,458 INFO [HibernateManager ] | Adding this resource to hibernate now : com/cargosoft/csedi/data/adr/Adr_DEV.hbm.xml 07:36:21,495 INFO [HibernateManager ] | Adding this resource to hibernate now : com/cargosoft/csedi/data/adraesort/Adraesort_DEV.hbm.xml 07:36:21,523 INFO [HibernateManager ] | Adding this resource to hibernate now : com/cargosoft/csedi/data/adrakte/Adrakte_DEV.hbm.xml ... 07:36:23,475 INFO [HibernateManager ] | Adding this resource to hibernate now : com/cargosoft/csedi/data/zollanmtxt/Zollanmtxt_DEV.hbm.xml 07:36:23,477 INFO [HibernateManager ] | Adding this resource to hibernate now : com/cargosoft/csedi/data/sstbasis/Sstbasis_DEV.hbm.xml 07:36:23,479 INFO [HibernateManager ] | Adding this resource to hibernate now : com/cargosoft/csedi/data/sststruktur/Sststruktur_DEV.hbm.xml 07:36:23,481 INFO [HibernateManager ] | Adding this resource to hibernate now : com/cargosoft/csedi/data/ssthandler/Ssthandler_DEV.hbm.xml 07:36:23,482 INFO [HibernateManager ] | Adding this resource to hibernate now : com/cargosoft/csedi/data/sstproperty/Sstproperty_DEV.hbm.xml 07:36:23,484 INFO [HibernateManager ] | Adding this resource to hibernate now : com/cargosoft/csedi/data/sstprophandler/Sstprophandler_DEV.hbm.xml 07:36:23,486 INFO [HibernateManager ] | Adding this resource to hibernate now : com/cargosoft/csedi/data/sstneustart/Sstneustart_DEV.hbm.xml 07:36:23,488 INFO [HibernateManager ] | Create new SessionFactory for: jdbc:informix-sqli://... 

随着hibernate 4.3.8-Final:

  07:38:04,749 INFO [HibernateManager ] | Verwende Mapping-Collection Datei : /de/cargosoft/edi/cargoservice/entities/mappings_dev.xml 07:38:04,824 INFO [HibernateManager ] | Adding this resource to hibernate now : de/cargosoft/edi/cargoservice/entities/aart/Aart_DEV.hbm.xml 07:38:05,249 INFO [HibernateManager ] | Adding this resource to hibernate now : de/cargosoft/edi/cargoservice/entities/abteilung/Abteilung_DEV.hbm.xml 07:38:05,527 INFO [HibernateManager ] | Adding this resource to hibernate now : de/cargosoft/edi/cargoservice/entities/adr/Adr_DEV.hbm.xml 07:38:05,792 INFO [HibernateManager ] | Adding this resource to hibernate now : de/cargosoft/edi/cargoservice/entities/adraesort/Adraesort_DEV.hbm.xml 07:38:06,077 INFO [HibernateManager ] | Adding this resource to hibernate now : de/cargosoft/edi/cargoservice/entities/adrakte/Adrakte_DEV.hbm.xml ... 07:40:14,119 INFO [HibernateManager ] | Adding this resource to hibernate now : de/cargosoft/edi/cargoservice/entities/zollanmtxt/Zollanmtxt_DEV.hbm.xml 07:40:14,499 INFO [HibernateManager ] | Adding this resource to hibernate now : de/cargosoft/edi/cargoservice/entities/sstbasis/Sstbasis_DEV.hbm.xml 07:40:14,746 INFO [HibernateManager ] | Adding this resource to hibernate now : de/cargosoft/edi/cargoservice/entities/sststruktur/Sststruktur_DEV.hbm.xml 07:40:14,972 INFO [HibernateManager ] | Adding this resource to hibernate now : de/cargosoft/edi/cargoservice/entities/ssthandler/Ssthandler_DEV.hbm.xml 07:40:15,211 INFO [HibernateManager ] | Adding this resource to hibernate now : de/cargosoft/edi/cargoservice/entities/sstproperty/Sstproperty_DEV.hbm.xml 07:40:15,434 INFO [HibernateManager ] | Adding this resource to hibernate now : de/cargosoft/edi/cargoservice/entities/sstprophandler/Sstprophandler_DEV.hbm.xml 07:40:15,657 INFO [HibernateManager ] | Adding this resource to hibernate now : de/cargosoft/edi/cargoservice/entities/sstneustart/Sstneustart_DEV.hbm.xml 07:40:15,878 INFO [HibernateManager ] | Create new SessionFactory for: jdbc:informix-sqli://... 

添加映射文件的方法如下所示:

  for (Node node : nodes) { Element element = (Element) node; String resource = element.attributeValue("resource"); logger.info("Adding this resource to hibernate now : " + resource); configuration.addResource(resource); } 

时间不足是在addResource上

我们还通过将映射元素直接移动到hibernate.cfg.xml文件来尝试它,但启动时需要相同的时间。

我们相信hibernate正在validationhibernate 3没有的东西。

有人有想法解决这个问题吗? 我们不能等待每个测试运行2分钟。

Hauke,非常感谢和许多问候

UPDATE

我将loglevel改为“DEBUG”,现在它来了:

我改为loglevel进行调试,现在就出来了:

  11:29:22,781 INFO [HibernateManager ] | Adding this resource to hibernate now : de/cargosoft/edi/cargoservice/entities/aart/Aart_DEV.hbm.xml 11:29:22,782 INFO [Configuration ] | HHH000221: Reading mappings from resource: de/cargosoft/edi/cargoservice/entities/aart/Aart_DEV.hbm.xml 11:29:22,804 DEBUG [DTDEntityResolver ] | Trying to resolve system-id [http://hibernate.org/dtd/hibernate-mapping-3.0.dtd] 11:29:23,149 INFO [HibernateManager ] | Adding this resource to hibernate now : de/cargosoft/edi/cargoservice/entities/abteilung/Abteilung_DEV.hbm.xml ... 

因此,似乎DTDEntityResolver每个实体需要大约200ms – 400ms。 有500个实体,这将总结。

所以问题是,如何禁用它?

您需要更改所有HBM配置文件的DTD:

 http://hibernate.org/dtd/hibernate-mapping-3.0.dtd 

至:

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

这是DTDEntityResolver尝试定位DTO的方式:

 public class DTDEntityResolver implements EntityResolver, Serializable { private static final String HIBERNATE_NAMESPACE = "http://www.hibernate.org/dtd/"; private static final String OLD_HIBERNATE_NAMESPACE = "http://hibernate.sourceforge.net/"; private static final String USER_NAMESPACE = "classpath://"; public InputSource resolveEntity(String publicId, String systemId) { InputSource source = null; // returning null triggers default behavior if ( systemId != null ) { LOG.debugf( "Trying to resolve system-id [%s]", systemId ); if ( systemId.startsWith( HIBERNATE_NAMESPACE ) ) { LOG.debug( "Recognized hibernate namespace; attempting to resolve on classpath under org/hibernate/" ); source = resolveOnClassPath( publicId, systemId, HIBERNATE_NAMESPACE ); } else if ( systemId.startsWith( OLD_HIBERNATE_NAMESPACE ) ) { LOG.recognizedObsoleteHibernateNamespace( OLD_HIBERNATE_NAMESPACE, HIBERNATE_NAMESPACE ); LOG.debug( "Attempting to resolve on classpath under org/hibernate/" ); source = resolveOnClassPath( publicId, systemId, OLD_HIBERNATE_NAMESPACE ); } else if ( systemId.startsWith( USER_NAMESPACE ) ) { LOG.debug( "Recognized local namespace; attempting to resolve on classpath" ); String path = systemId.substring( USER_NAMESPACE.length() ); InputStream stream = resolveInLocalNamespace( path ); if ( stream == null ) { LOG.debugf( "Unable to locate [%s] on classpath", systemId ); } else { LOG.debugf( "Located [%s] in classpath", systemId ); source = new InputSource( stream ); source.setPublicId( publicId ); source.setSystemId( systemId ); } } } return source; } ... } 

Hibernate无法在hibernate-core-4.3.8.Final.jar找到hibernate-mapping-3.0.dtd配置文件,所以它会通过你所有的类路径进行处理,因为你有一个庞大的项目,这解释了为什么它开始这么慢。

我曾经使用一个技巧在解析XML文件时跳过DTDvalidation,使用下面的代码。 您的情况更复杂,因为您需要将其插入Hibernate配置解析器。 但它可能会让你开始。

 private boolean skipDtd = true; // TODO make configurable private EntityResolver dummyDtdResolver = new EntityResolver() { @Override public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException { if (skipDtd && systemId.toLowerCase().endsWith(".dtd")) return new InputSource(new StringReader("")); return null; } }; 

几种使用方法:

  1. 来自DocumentBuilder

     DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); DocumentBuilder parser = dbf.newDocumentBuilder(); parser.setEntityResolver(dummyDtdResolver); ... parser.parse(new File(xmlName)); 
  2. 来自XmlReader

     SAXParserFactory saxParserFactory = SAXParserFactory.newInstance(); saxParserFactory.setNamespaceAware(true); XMLReader xmlReader = saxParserFactory.newSAXParser().getXMLReader(); xmlReader.setEntityResolver(dummyDtdResolver); ... new SAXSource(xmlReader, inputSource);