Spring Data JPA配置级联后新增Mathematics触发question_id非空报错求解
问题原因
- 你配置的是双向一对一关联,
mappedBy = "maths"说明MathsAnswers是关联关系的维护端,外键question_id的值由MathsAnswers实体的maths关联属性控制。你直接在Mathematics实体中初始化了answers = new MathsAnswers(),但没有给这个answers实例设置maths属性指向当前的Mathematics对象,级联保存时MathsAnswers对应的question_id字段自然为空,触发非空约束报错。 - 你当前的POST请求没有传递答案相关数据,初始化的空
MathsAnswers实例不仅question_id为空,表结构要求非空的question_no字段也没有值,就算解决了外键问题也会触发第二个非空约束报错。 - 额外不兼容点:
Mathematics实体主键用了GenerationType.SEQUENCE生成策略,但你用的MySQL数据库不支持序列,表结构中主键是auto_increment自增,策略不匹配也会引发主键生成异常。
解决方案
方案一:允许新增问题时暂不提交答案(推荐)
直接移除Mathematics实体中answers属性的初始化代码即可:
// 修改前 private MathsAnswers answers = new MathsAnswers(); // 修改后 private MathsAnswers answers;
修改后如果POST请求不传答案数据,answers为null,JPA就不会级联插入MATHS_ANSWER表的记录,不会触发非空约束报错,后续需要提交答案时再单独维护关联关系即可。
方案二:要求新增问题时必须同步提交答案
- 首先补全
MathsAnswers实体的关联配置:
@Entity @Table(name = "MATHS_ANSWER") public class MathsAnswers { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer id; @Column(name = "date") private Date date; @Column(name = "question_no") private Integer questionNo; @Column(name = "solution") private String solution; @Column(name = "solution_url") private String solutionUrl; // 关联主实体,对应外键question_id @OneToOne @JoinColumn(name = "question_id", referencedColumnName = "id", nullable = false) private Mathematics maths; // 省略getter、setter }
- 在
Mathematics实体中新增预保存回调,自动维护关联关系,避免手动赋值遗漏:
@PrePersist public void prePersist() { if (answers != null) { // 绑定关联关系,自动填充question_id外键 answers.setMaths(this); // 同步questionNo字段,无需前端重复传值 answers.setQuestionNo(this.getQuestionNo()); } }
- 修正
Mathematics实体的主键生成策略适配MySQL:
// 修改前 @GeneratedValue(strategy = GenerationType.SEQUENCE) // 修改后 @GeneratedValue(strategy = GenerationType.IDENTITY)
- POST请求同步携带答案字段即可:
{ "year":"2004-01-03", "questionNo":"4", "question":"一年有多少周?", "answers": { "date": "2004-01-04", "solution": "52周" } }
内容的提问来源于stack exchange,提问作者Chinedu
相关产品推荐
相关产品推荐

