Spring添加@Scheduled注解后出现Hibernate no Session错误是什么原因
错误原因分析
基础错误本质
could not initialize proxy [ABC#8] - no Session属于Hibernate典型的懒加载会话丢失异常:当你给实体的关联属性配置了懒加载策略时,Hibernate查询主实体时不会直接查询关联属性,只会返回一个代理对象,只有在该查询所属的Hibernate Session生命周期内访问这个代理对象的属性,才会自动触发二次查询拉取关联数据;如果Session已经被关闭,再访问代理对象就会抛出该异常。
不加@Scheduled时运行正常的原因
常规业务请求场景下,Spring默认有会话绑定逻辑:要么是通过OpenSessionInViewFilter将Session生命周期和web请求绑定,请求全流程Session保持开启;要么是业务方法加了@Transactional注解,事务范围内Session一直存活。所以你访问懒加载属性时Session还处于活跃状态,不会触发报错。
加@Scheduled后触发报错的根本原因
@Scheduled注解标记的方法是由Spring独立的调度线程池执行的,和常规web请求线程完全隔离,没有默认的Session绑定机制:
- 调度线程执行业务方法时,不会自动开启并绑定Hibernate Session到上下文
- 结合你的报错栈来看,
xyzService.customMethod中大概率存在以下逻辑:先查询获取了ABC实体的懒加载代理对象,后续访问该代理的关联属性时,之前查询所用的Session已经被关闭,没有可用Session触发懒加载查询 - 最常见的场景是该业务方法没有加
@Transactional注解,或者查询操作和懒加载属性访问拆分到了两个独立的事务中,前一个事务结束时Session就被关闭,后续访问属性就会触发异常。
推荐修复方案
- 方案1:给
@Scheduled标记的业务方法添加@Transactional注解,确保整个方法执行周期内Session保持活跃,懒加载可以正常触发 - 方案2:调整查询逻辑,查询ABC实体时通过HQL的
join fetch主动拉取需要用到的关联属性,或者将对应关联属性的加载策略改为FetchType.EAGER,从根源上避免后续懒加载 - 方案3:针对定时任务调用的业务逻辑单独封装,直接编写SQL查询所有需要的字段,不依赖Hibernate的懒加载机制
内容的提问来源于stack exchange,提问作者Tharindu Lakshan
相关产品推荐
相关产品推荐

