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

运行时可获取嵌套集合,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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 19:05:22