运行时可获取嵌套集合,JUnit5+H2测试时却为null求助
问题原因与解决方案
核心原因
@OneToMany关联默认采用懒加载(FetchType.LAZY):
- 运行时通常有事务上下文或Open Session in View机制,访问集合时Hibernate会自动初始化;
- 测试场景中,查询完成后会话立即关闭,懒加载的集合未被初始化,因此返回null。
另外你的查询语句存在参数绑定错误:@Query里写的是:loanContract,但@Param标注的是"number",这会导致参数无法正确匹配,需修正为:number。
解决方案
方案1:修改关联为立即加载
在@OneToMany注解中显式指定fetch = FetchType.EAGER,强制查询CarEntity时同时加载wheels集合:
@OneToMany(cascade = CascadeType.ALL, mappedBy = "car", fetch = FetchType.EAGER) private List<WheelEntity> wheels;
注意:此方式会每次查询都加载关联集合,生产环境需评估性能影响,测试场景可放心使用。
方案2:使用JOIN FETCH显式加载关联
修改查询语句,通过JOIN FETCH在查询时一次性加载关联集合:
@Query("SELECT c FROM car c JOIN FETCH c.wheels WHERE c.number=:number") Optional<CarEntity> findByNumber(@Param("number") String number);
此方式更灵活,仅在需要加载关联时执行关联查询,避免不必要的性能损耗。
方案3:让测试方法在事务内执行
给JUnit测试方法添加@Transactional注解,确保查询后会话保持打开,访问集合时Hibernate会自动初始化懒加载数据:
import org.junit.jupiter.api.Test; import org.springframework.transaction.annotation.Transactional; @Test @Transactional void testFindCarWithWheels() { // 测试逻辑:查询CarEntity并访问wheels集合 Optional<CarEntity> carOpt = carRepository.findByNumber("test-number"); carOpt.ifPresent(car -> { // 此时wheels会被懒加载初始化 System.out.println(car.getWheels().size()); }); }
内容的提问来源于stack exchange,提问作者jo23
相关产品推荐
相关产品推荐

