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

创建Java更新API遇EntityNotFoundException,困惑DTO与Entity类选择

问题解决与方案建议

一、EntityNotFoundException 异常修复

1. 先修正代码笔误

你的Controller里调用findById时写错了Repository变量名:orgStudentRepo应该是ogStudentRepo,这是明显的拼写错误,会导致逻辑异常。

2. 排查数据存在性

如果修正笔误后仍抛出异常,说明传入的ogStudentId在数据库中不存在:

  • 检查Liquibase生成的og_student表,确认是否有对应ID的记录
  • 验证请求路径中的{ogStudentId}参数是否正确(注意String类型主键大小写敏感,避免空格、格式错误)
  • 可添加日志打印实际传入的ID,方便排查:
    log.info("尝试更新学生ID: {}", ogStudentId);
    

3. 移除冗余代码

orElseThrow在找不到数据时已经抛出异常,后续的if(existingStudent == null)判断完全多余,直接删掉即可。

修复后的Controller方法:

@PutMapping("/update/{ogStudentId}")
public ResponseEntity<String> updateStudent(@PathVariable String ogStudentId, @RequestBody OgStudent ogStudent){
    log.info("尝试更新学生ID: {}", ogStudentId);
    OgStudent existingStudent = ogStudentRepo.findById(ogStudentId)
            .orElseThrow(() -> new EntityNotFoundException("OG学生不存在"));

    existingStudent.setFirstName(ogStudent.getFirstName());
    existingStudent.setLastName(ogStudent.getLastName());
    existingStudent.setMiddleName(ogStudent.getMiddleName());

    ogStudentRepo.save(existingStudent);
    return ResponseEntity.ok("更新成功");
}

二、DTO类 vs Entity类的选择建议

为什么不直接用Entity接收请求?

  • 敏感字段暴露风险:你的Entity包含email、dob等字段,直接用它接收请求时,客户端可能传入这些字段并被意外修改(哪怕当前代码没处理,后续迭代也容易出问题)。
  • 耦合性过高:Entity与数据库表结构强绑定,表结构变更时,接口请求参数也被迫修改,不符合开闭原则。
  • 校验逻辑混乱:请求参数的校验(非空、格式验证等)应该和持久层代码分离,避免污染Entity。

如何实现DTO?

  1. 创建仅包含需要更新字段的DTO类:
import jakarta.validation.constraints.NotBlank;
import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
public class UpdateStudentDTO {
    @NotBlank(message = "名不能为空")
    private String firstName;
    private String middleName;
    @NotBlank(message = "姓不能为空")
    private String lastName;
}
  1. 修改Controller方法,用DTO接收请求并添加参数校验:
@PutMapping("/update/{ogStudentId}")
public ResponseEntity<String> updateStudent(@PathVariable String ogStudentId, 
                                            @Valid @RequestBody UpdateStudentDTO updateStudentDTO){
    log.info("尝试更新学生ID: {}", ogStudentId);
    OgStudent existingStudent = ogStudentRepo.findById(ogStudentId)
            .orElseThrow(() -> new EntityNotFoundException("OG学生不存在"));

    existingStudent.setFirstName(updateStudentDTO.getFirstName());
    existingStudent.setLastName(updateStudentDTO.getLastName());
    existingStudent.setMiddleName(updateStudentDTO.getMiddleName());

    ogStudentRepo.save(existingStudent);
    return ResponseEntity.ok("更新成功");
}
  1. 确保项目引入spring-boot-starter-validation依赖(Spring Boot 3.x需手动添加),并在启动类/配置类添加@Validated注解开启校验。

总结

  • 前端请求用DTO接收:隔离业务层与持久层,降低耦合,避免敏感字段暴露。
  • Entity仅用于数据库交互:作为持久化对象,不直接暴露给接口层。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 18:04:58