升级Spring Boot 3.2后遭遇LazyInitializationException如何解决?
Spring Boot 3.2.0升级后LazyInitializationException问题
问题描述
- 项目从Spring Boot 3.1.12升级至3.2.0后,访问父实体的子实体时触发
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: could not initialize proxy - no Session异常 - Spring Boot 3.2.0的
spring-boot-starter-jpa依赖Hibernate 6.3,其迁移指南中「Batch Fetching and LockMode」章节的新行为疑似为问题诱因 - 尝试过
@EntityGraph与fetch join查询方案,但会大幅增加接口响应时间——Hibernate会为每个父实体生成2个fetch join查询,父实体数量较多时性能影响显著 - 基于Spring Data JPA开发,相关方法已标注
@Transactional且此前运行正常,异常出现在childItems = it.transfers.toDto()代码行
相关代码
业务逻辑伪代码
@Transactional override suspend fun report(...) { val items = loadItems(...) toItemsReport(items, ...) } private suspend fun loadItems(...) = withContext(Dispatchers.IO) { val criteria: Specification<ItemEntity> = ... val items = itemRepository.findAll(criteria, page) items } private suspend fun toItemsReport(items, ...) { return ItemExport( slice = items, reports = items.map { ItemExport( item = it.toDto(), childItems = it.transfers.toDto() ) } ) }
Item仓库定义
interface ItemRepository: JpaRepository<ItemEntity, Int>, JpaSpecificationExecutor<ItemEntity> { override fun findAll(spec: Specification<ItemEntity>, pageable: Pageable): Page<ItemEntity> }
可行解决思路
- 协程事务上下文校验:Spring的
@Transactional在协程环境下,需确保事务上下文在withContext(Dispatchers.IO)切换后仍有效。可尝试移除loadItems中的协程上下文切换逻辑,或使用Spring适配协程的事务处理方式,保证Session绑定不丢失 - 提前初始化懒加载集合:在事务范围内(
loadItems方法内),获取items后遍历并调用Hibernate.initialize(it.transfers),强制在Session关闭前加载子集合,避免后续访问时触发懒加载异常 - 优化批量抓取配置:在子实体集合的字段上添加
@BatchSize(size = 50)注解,让Hibernate批量加载子集合,减少查询次数,替代fetch join带来的性能问题 - 临时应急方案(不推荐生产):设置Hibernate属性
hibernate.enable_lazy_load_no_trans=true,允许在事务外触发懒加载,但该配置可能引发Session泄漏等风险,仅建议用于临时排查
内容的提问来源于stack exchange,提问作者Arseniy
相关产品推荐
相关产品推荐

