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

Spring JPA中getById方法返回null、获取Hibernate代理对象问题排查

问题根因分析

  • getById方法的代理特性
    Spring Data JPA 中getById底层调用Hibernate的load方法,默认返回延迟加载代理对象,不会立即执行数据库查询。只有访问代理对象的非主键属性时才会触发查库操作,如果对应ID的记录不存在,此时才会抛出异常或返回空值,debug时看到的ExerciseEntity$HibernateProxy$xxx就是代理对象而非真实实体,很容易被误认为是null。
  • ExerciseEntity主键缺少生成策略
    当前ExerciseEntity的@Id注解下没有配置主键生成策略,如果插入ExerciseEntity数据时没有手动指定ID值,数据库中对应记录的主键为空或不符合预期,查询时自然匹配不到对应记录。
  • 双向关联维护缺失(非直接报错原因,但会引发后续缓存不一致问题)
    配置的是双向多对多关联,当前仅给PersonalTrainingProgram设置了关联的运动实体集合,没有同步给ExerciseEntity的关联集合赋值,后续查询可能出现关联数据缺失的问题。

修复方案

  1. 替换getById为findById,主动判空
    findById会立即触发数据库查询,返回真实实体对象,不存在的话返回空Optional,方便提前排查无效ID:
@Override
public List<ExerciseEntity> findExercisesBySpecificId(List<ExerciseDto> exerciseDto) {
    List<ExerciseEntity> listEntity= new ArrayList<>();
    for (ExerciseDto dto : exerciseDto) {
        Optional<ExerciseEntity> exerciseOpt = exercisesRepository.findById(dto.getId());
        exerciseOpt.ifPresent(listEntity::add);
        // 可在这里添加日志或者异常逻辑,排查无效ID
        if (exerciseOpt.isEmpty()) {
            System.out.printf("ID为%d的运动记录不存在%n", dto.getId());
        }
    }
    return listEntity;
}
  1. 给ExerciseEntity添加主键生成策略
    如果使用数据库自增主键,补充@GeneratedValue注解:
@Entity
@Table(name = "exercises")
public class ExerciseEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    // 其余属性保持不变
}
  1. 同步维护双向关联关系
    保存训练计划时同步更新运动实体的关联集合:
@Override
public void addItToDatabase(List<ExerciseDto> exerciseDto, FoodProgramDto foodProgramDto,String username) {
    PersonalTrainingProgram personalTrainingProgram = new PersonalTrainingProgram();
    List<ExerciseEntity> exercises = findExercisesBySpecificId(exerciseDto);
    personalTrainingProgram.setExerciseEntityList(exercises);
    // 同步维护ExerciseEntity端的关联
    exercises.forEach(exercise -> exercise.getPersonalTrainingPrograms().add(personalTrainingProgram));
    personalTrainingProgram.setFoodProgram(foodProgramService.findFoodProgramById(foodProgramDto));
    personalTrainingProgram.setAppUser(appUserRepository.findByUsername(username).get());
    personalTrainingRepository.save(personalTrainingProgram);
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 16:24:01