首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >迁移到Hibernate 5.6 (Java 16)的遗留项目具有缓慢的一对一双向性能

迁移到Hibernate 5.6 (Java 16)的遗留项目具有缓慢的一对一双向性能
EN

Stack Overflow用户
提问于 2021-12-08 17:09:31
回答 1查看 296关注 0票数 0

我正在将遗留的hibernate项目从版本4.3 (使用Java 11)迁移到5.6 (使用Java 16)。下面的HBM文件映射了管辖权-> Unit -> UnitAux的对象图。单位是懒惰加载,UnitAux是一对一的单位.在4.3版下,当初始化单元时,加载大约需要100 to。在5.6版下,它现在需要600到800毫秒。

以下是三个实体的缩写HBM文件:

Jurisdiction.hbm.xml

代码语言:javascript
运行
复制
<hibernate-mapping>
  <class name="com.edc.c2c.core.model.impl.Jurisdiction" table="Jurisdiction" schema="domain" dynamic-update="true">
    
    <set name="units" 
        inverse="true" cascade="all" lazy="true" fetch="select" 
        optimistic-lock="false" batch-size="1000" where="recordStatus = 'A'">
        <key>
            <column name="jurisdictionId"/>
        </key>
        <one-to-many class="com.edc.c2c.core.model.impl.Unit"/>
    </set>

  </class>
</hibernate-mapping>

Unit.hbm.xml

代码语言:javascript
运行
复制
<hibernate-mapping>
  <class name="com.edc.c2c.core.model.impl.Unit" table="Unit" schema="domain" dynamic-update="false">
  
  <composite-id>
        <key-property name="id"                   column="id"             type="long"/>
        <key-property name="owningJurisdictionId" column="jurisdictionId" type="long"/>
    </composite-id>
    
    <one-to-one name="unitAux" class="com.edc.c2c.core.model.impl.UnitAux" cascade="all" fetch="join" property-ref="unit"/>
  
  </class>
</hibernate-mapping>

UnitAux.hbm.xml

代码语言:javascript
运行
复制
<hibernate-mapping>
  <class name="com.edc.c2c.core.model.impl.UnitAux" table="UnitAux" schema="domain" dynamic-update="true">
  
  <composite-id>
        <key-property name="id"             column="id"             type="long"/>
        <key-property name="jurisdictionId" column="jurisdictionId" type="long"/>
    </composite-id>
    
    <many-to-one name="unit" class="com.edc.c2c.core.model.impl.Unit" unique="true" not-null="true" 
        cascade="all" insert="false" update="false">
        <column name="id"/>
        <column name="jurisdictionId"/>
    </many-to-one>
    
  </class>
</hibernate-mapping>

如果我在Unit.hbm.xml,中注释掉一对一的话,这个单元就会像预期的那样快速加载。

在UnitAux.hbm.xml中,我用一个包含一对多的袋子替换了多对一的,类似这样的东西:

代码语言:javascript
运行
复制
<bag name="unitGroup" inverse="true" cascade="all" lazy="true" fetch="select">
  <key>
      <column name="id"/>
      <column name="jurisdictionId"/>
  </key>
  <one-to-many class="com.edc.c2c.core.model.impl.unit"/>
</bag>

这样,UnitAux类就有了一个名为unitGroup的List属性。随着袋子,单位(S)的装载时间下降到300毫秒。

我不知道如何让hibernate 5.6在与4.3相同的加载时间内执行。

如有任何意见或建议,将不胜感激。

更新:我忘了提到的,这两个版本有效地产生了相同的。有关如何初始化对象本身的内容一定是导致速度减慢的原因。

更新2: 4.3和5.6之间的会话统计数据非常相似;不足以解释性能差异。我的调查显示,延迟似乎集中在初始化实体。特别是,呼吁

代码语言:javascript
运行
复制
Loader.initializeEntitiesAndCollections( final List hydratedObjects, final Object resultSetId, final SharedSessionContractImplementor session, final boolean readOnly, List<AfterLoadAction> afterLoadActions)

在这里花费的时间是延迟的所在。每个实体中的每个属性都进行字节码增强测试。在我的测试中,我将加载600+单元以及600+ UnitAux实体。比不做这个的替代加载程序更好吗?

更新3:将单元-> UnitAux的关联更改为单向,减少了大约一半的延迟。现在它只慢了3倍。

更新4: --这很奇怪。在对各种事物进行了实验之后,我做出了如下发现。如果我为hibernate启用了信息(或错误)级别的日志记录(请参见下面的配置),那么一切都会在预期的时间内快速运行:

代码语言:javascript
运行
复制
<logger name="org.hibernate" additivity="false">
    <level value="info"/>
    <appender-ref ref="STDOUT"/>
</logger>

如果未声明日志记录,则运行缓慢(这意味着没有为hibernate专门配置任何内容)。这对jboss来说是很奇怪的吗?我使用的是jboss 3.4.2.final.jar。如果log4j.xml中没有显式声明,它是否运行得更慢?这就像一个典型的问题:调试语句永远不会被使用,但是Java必须构建所有的字符串值,这会导致极大的延迟。

更新5:我刚刚对Hibernate Core5.6.0-Final的源代码进行了抽查。141个类使用log.trace,249个类使用log.debug。大多数log.trace调用都没有预先检查是否启用了跟踪。log.debug调用被检查得更频繁,但是仍然有很多不预先检查是否启用了调试。

EN

回答 1

Stack Overflow用户

发布于 2021-12-22 14:36:27

最后,我找到了自己对这个问题的答案。

首先,Hibernate 5.x和一对一的双向关联根本没有问题.这个问题与调试/跟踪日志记录有关。随着Hibernate 5.x和字节码的增强,增加了许多新的日志记录。不仅对每个逐行实体进行日志记录,而且对每个列/属性(测试列延迟加载?)进行日志记录。

其次,我的实体类对toString()有特殊的格式设置。这些toString()的调用可能需要很长时间才能执行,如果超过数百个实体,则会乘以。

第三,和log4j1-12.x之间一定有一些错误。在内部,jboss#doLogf()检查是否启用了日志记录级别,但是它仍然到达字符串格式化程序。下面是运行在Tomcat中的应用程序的VisualVM快照;您可以看到,为调试格式化添加了700 is,尽管它永远不会打印到日志文件中:

如果Hibernate代码在日志记录调用之前进行了调试/跟踪级别检查,则不会发生这种情况。

最后,使用Tomcat,我删除了所有log4j和slf4jlog4jJAR文件。解决了问题。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70279037

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档