OpenJPA升级至Hibernate后批处理作业性能骤降问题求助
Spring+ORM框架升级后Hibernate批处理性能骤降问题求助
背景说明
我们原使用Open JPA 2.4.3搭配Spring 4.3.19.RELEASE,后续升级为Hibernate 5.4.8.Final搭配Spring 5.2.6.RELEASE。由于Spring 5.0及对应版本的Spring Data未提供OpenJPA厂商适配器,我们不得不更换ORM实现。升级后批处理作业出现严重性能问题,运行耗时是此前的10倍,目前我们暂时将性能不达标的查询改为Native SQL查询临时解决。
排查发现
从性能转储数据中我们发现,Hibernate的Session在事务提交后未被释放。另外我们还观察到OpenJPA使用WeakHashMap、Hibernate使用ConcurrentHashMap,暂不确定该差异是否与性能问题相关。
请问是否有人遇到过同类问题,对应的解决方法是什么?
性能对比截图
解决方案
针对该场景下的性能问题,可按以下优先级依次排查修复:
- 配置Session自动释放规则
在Hibernate配置中显式指定hibernate.current_session_context_class为org.springframework.orm.hibernate5.SpringSessionContext,确保Spring事务提交后会自动关闭并释放关联的Session,避免Session累积占用内存。非JTA事务场景下无需额外配置事务管理器查找类。 - 优化批处理场景缓存策略
处理批量数据时,Hibernate默认会将所有持久化实体存放在一级缓存中,不会主动清理。需要每处理完10100条数据后,手动调用`session.flush()`和`session.clear()`同步数据到数据库并清理一级缓存。同时开启`hibernate.jdbc.batch_size`配置,建议设为2050,启用JDBC批量操作能力,降低IO开销。 - 关闭非必要的状态检查逻辑
只读批处理任务可在对应方法上添加@Transactional(readOnly = true)注解,关闭Hibernate的自动脏检查逻辑,大幅降低Session资源占用。写操作场景可在实体类上添加@DynamicUpdate注解,仅更新发生变化的字段,减少SQL执行开销。 - 缓存实现差异适配
Hibernate使用ConcurrentHashMap存储上下文数据,不会像OpenJPA的WeakHashMap一样自动回收闲置实体引用,这是导致性能差异的核心原因之一,通过前文提到的手动清理Session一级缓存即可解决,无需修改Hibernate核心实现。
以上调整完成后,批处理性能基本可以恢复到OpenJPA同期水平,无需全量替换为Native SQL。
内容的提问来源于stack exchange,提问作者Pavan
相关产品推荐
相关产品推荐



