使用Spring JPA发送带外键的POST请求时出现重复/空值错误如何解决
错误原因分析
- 首次报主键重复错误,核心原因是
DrivingStudent实体的@ManyToOne注解配置了cascade = CascadeType.ALL,保存学生实例时会级联尝试保存请求体中传递的临时状态DrivingInstructor对象,而该id对应的教练已存在于数据库,触发唯一约束冲突。 - 后续报外键列非空错误,核心原因是
@JoinColumn配置完全错误:referencedColumnName错误指向了父表的driving_instructor_name字段,应该指向父表主键driving_instructor_id- 额外添加了
insertable = false, updatable = false配置,导致外键列被设为只读,插入学生时无法写入外键值,触发非空约束。
修复步骤
第一步:修正DrivingStudent实体配置
@Entity(name = "DrivingStudent") @Table(name = "driving_student") @Getter @Setter @NoArgsConstructor public class DrivingStudent { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "driving_student_id") private long drivingStudentId; @Column(name = "driving_student_name") @Size(max = 128) private String drivingStudentName; // 移除不需要的cascade配置,修正@JoinColumn配置 @ManyToOne(targetEntity = DrivingInstructor.class) // 注意:如果你的driving_student表中外键列实际名叫driving_instructor_number,就把name改为对应值 @JoinColumn(name = "driving_instructor_id", referencedColumnName = "driving_instructor_id") private DrivingInstructor drivingInstructor; }
第二步:修正Controller层逻辑
修复你之前代码里的方法名笔误即可:
@RequestMapping(path = "api/v0/driving-school") @RestController @AllArgsConstructor public class DrivingStudentRestController { private final DrivingInstructorRepository drivingInstructorRepository; private final DrivingStudentServiceImpl drivingStudentServiceImpl; @PostMapping Long insertOrUpdateDrivingStudent(@Valid @RequestBody DrivingStudent drivingStudent) { Optional<DrivingInstructor> drivingInstructor = drivingInstructorRepository.findById(drivingStudent.getDrivingInstructor().getDrivingInstructorId()); if (drivingInstructor.isPresent()) { drivingStudent.setDrivingInstructor(drivingInstructor.get()); // 修正之前的方法名笔误 return drivingStudentServiceImpl.insertOrUpdateDrivingStudent(drivingStudent); } // 建议此处补全不存在对应教练时的异常返回逻辑,避免直接返回null throw new RuntimeException("对应教练不存在"); } }
验证
修改完成后再发送原POST请求即可正常插入学生数据,关联已有的教练实例,原有GET查询逻辑不受影响可正常返回关联数据。
内容的提问来源于stack exchange,提问作者dglz
相关产品推荐
相关产品推荐

