JPA单仓库保存关联对象失败:id_hour字段非空异常
问题解决:Hibernate保存关联对象时
id_hour为空报错 问题核心原因
报错本质是双向关联的关系未正确维护:
Hour与RegularHour是一对多双向关联,RegularHour是关联的拥有方(@JoinColumn定义在此类中,Hibernate以拥有方的关联状态为准)- 创建对象时,仅给
Hour的regularHours列表添加了RegularHour实例,但未给每个RegularHour设置对应的hour属性,导致插入regular_hour表时外键id_hour无值,触发非空约束错误。
解决方案
1. 在Hour类中添加关联维护方法
手动维护双向关联是最可靠的方式,在Hour中添加方法确保双方关联同步:
@Setter @Getter @Builder @AllArgsConstructor @NoArgsConstructor @Entity @Table(name = "hour") public class Hour { // 原有属性保持不变 // 替代直接操作regularHours列表,用此方法添加关联 public void addRegularHour(RegularHour regularHour) { this.regularHours.add(regularHour); regularHour.setHour(this); // 关键:给RegularHour设置对应的Hour引用 } // 可选:添加移除关联的方法 public void removeRegularHour(RegularHour regularHour) { this.regularHours.remove(regularHour); regularHour.setHour(null); } }
2. 创建对象时使用维护方法
构建对象流程中,调用addRegularHour替代直接操作列表:
// 构建RegularHour实例 RegularHour regularHour = RegularHour.builder() .weekday(1) .periodBegin("07:00") .periodEnd("18:00") .build(); // 构建Hour实例并初始化列表 Hour hour = Hour.builder() .twentyfourseven(false) .regularHours(new ArrayList<>()) .build(); // 用维护方法建立双向关联 hour.addRegularHour(regularHour); // 构建Location实例 Location location = Location.builder() .id("LOC001") .hour(hour) .build(); // 执行保存 locationRepository.save(location);
3. 可选:自定义Lombok Builder自动维护关联(进阶)
如果依赖Lombok的@Builder,可自定义Builder自动同步关联(注意此方式需注意Builder生命周期):
@Setter @Getter @AllArgsConstructor @NoArgsConstructor @Entity @Table(name = "hour") public class Hour { // 原有属性不变 @OneToMany(mappedBy="hour", cascade = CascadeType.ALL) private List<RegularHour> regularHours = new ArrayList<>(); // 自定义Builder public static class HourBuilder { private List<RegularHour> regularHours = new ArrayList<>(); public HourBuilder regularHour(RegularHour regularHour) { this.regularHours.add(regularHour); regularHour.setHour(this.build()); return this; } public HourBuilder regularHours(List<RegularHour> regularHours) { regularHours.forEach(rh -> rh.setHour(this.build())); this.regularHours = regularHours; return this; } } }
验证效果
修改后执行保存操作,Hibernate会先插入hour表获取自动生成的id_hour,再插入regular_hour时自动填充该外键值,即可解决非空报错问题。
内容的提问来源于stack exchange,提问作者Serdar
相关产品推荐
相关产品推荐

