You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SpringBoot Test整合JPA时FetchType.LAZY触发no session异常问题

问题1解答:仅测试username为什么会访问roles字段

你用到了Lombok的@Data注解,该注解会自动为实体类生成包含所有字段的toString、equals、hashCode方法。你调用的AssertJ断言方法hasFieldOrPropertyWithValue在断言失败时,会调用被测对象的toString方法打印完整对象信息用于错误提示,这一过程会遍历所有字段包括roles、jobs等关联集合,因此触发了对懒加载属性的访问。

问题2解答:为什么出现no Session报错

Hibernate的懒加载机制要求:访问未初始化的懒加载代理属性时,必须处于该对象关联的持久化Session上下文中。你的测试逻辑里,userRepository.findById执行完成后,对应的Session就会自动关闭,此时返回的User对象中roles、jobs都是未初始化的代理对象。后续断言失败调用toString访问代理属性时,Session已经关闭,无法完成代理初始化,就会抛出LazyInitializationException。

问题3解答:该场景最佳实践

  • 优先修改断言逻辑:直接获取目标字段后再做断言,避免触发整个对象的toString,示例代码如下:
@Test
public void testQueryUser(){
    User user1 = userRepository.findById(12L).orElse(null);
    // 直接断言username,不会访问其他关联字段
    assertThat(user1.getUsername()).isEqualTo("adam");
}
  • 调整JPA实体的Lombok注解:不要在带关联关系的JPA实体上直接使用@Data,改用拆分的注解,同时排除关联字段避免自动生成的方法触发懒加载:
// 替换@Data为以下注解,排除所有关联属性避免toString/equals等方法触发懒加载
@Getter
@Setter
@ToString(exclude = {"roles", "jobs", "dept"})
@EqualsAndHashCode(exclude = {"roles", "jobs", "dept"}, callSuper = true)
@NoArgsConstructor
@AllArgsConstructor
@DynamicUpdate
@Entity
@Table(name = "sys_user")
public class User extends BaseEntity implements Serializable{
    // 原有字段逻辑不变
}
  • 确需在测试中访问懒加载属性的场景:给测试方法添加@Transactional注解,让整个测试方法执行期间Session保持开启,支持懒加载属性的正常初始化。

内容的提问来源于stack exchange,提问作者Alex

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 11:39:05