Hibernate使用ScrollableResults遍历数据时System.identityHashCode耗时过高问题
解答
问题1:纯只读场景是否可以避免调用StatefulPersistenceContext.addEntity、无需使用持久化上下文
可以,核心解决方案有两种:
- 优先使用
StatelessSession替代现有有状态Session执行查询:无状态会话天生不维护一级缓存、不管理实体生命周期、不会创建EntityEntry存入持久化上下文,从根源上避免addEntityEntry相关逻辑调用,完全适配你这种纯只读批量遍历的场景。修改后的查询代码参考:
CriteriaQuery query = ...; // 先 unwrap 出 SessionFactory 再打开无状态会话 StatelessSession statelessSession = entityManager.unwrap(Session.class).getSessionFactory().openStatelessSession(); ScrollableResults results = statelessSession.createQuery(query) .setFetchSize(20000) .setCacheable(false) .scroll(ScrollMode.FORWARD_ONLY); // 遍历完成后注意关闭 statelessSession 释放资源
- 改用投影查询返回DTO或Object数组:如果你不需要完整的实体对象,只需要部分字段,可以直接声明投影返回非实体类结果,Hibernate不会将这类结果纳入持久化上下文管理,也能跳过
addEntity逻辑。
问题2:System.identityHashCode执行速度优化相关问题
System.identityHashCode是JVM提供的native方法,计算的是对象在JVM层面的原生哈希值,和实体类的属性数量、属性类型完全无关,所以你将LocalDate改为Integer的改动,不会降低该方法的调用耗时。- 你当前场景下该方法占比过高的核心原因是数百万次调用的累计损耗,最优优化方案就是采用问题1给出的方案跳过持久化上下文,直接避免该方法的调用,远比优化方法本身的收益高。
内容的提问来源于stack exchange,提问作者Depressio
相关产品推荐
相关产品推荐

