Spring JPA保存Survey时报错:Field 'survey_id'无默认值
问题:保存/更新Survey时触发Field 'survey_id'无默认值错误
保存或更新包含sections和questions的Survey数据时,出现如下错误:
java.sql.SQLException: Field 'survey_id' doesn't have a default value
关联表survey_section_question已成功创建,查询现有数据可返回预期对象,但保存/更新操作失败。以下是相关代码:
实体代码
Survey类
@Entity @Table(name="Surveys") @Data public class Survey { @Id @Column(name = "id") @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name; private String description; private String createdBy; @ManyToMany(fetch = FetchType.EAGER, cascade = { CascadeType.PERSIST, CascadeType.MERGE }) @JoinTable( name = "survey_section_question", joinColumns = @JoinColumn(name = "survey_id"), inverseJoinColumns = @JoinColumn(name = "section_id") ) private List<SurveySection> sections; }
SurveySection类
@Entity @Table(name="SurveySections") @Data public class SurveySection { @Id @Column(name = "id") @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name; private String description; @ManyToMany @JoinTable( name = "survey_section_question", joinColumns = @JoinColumn(name = "section_id"), inverseJoinColumns = @JoinColumn(name = "question_id") ) private List<SurveyQuestion> questions; }
SurveyQuestion类
@Entity @Table(name="SurveyQuestions") @Data public class SurveyQuestion { @Id @Column(name = "id") @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name; private String description; private String createdBy; private boolean textAnswer; private boolean gradeAnswer; }
请求JSON
{"id":1,"name":"mu","description":"sss","createdBy":"xx","sections":[{"id":5,"name":"s2","description":"","questions":[{"id":15,"name":"adawd","description":"awdawd","createdBy":"","textAnswer":true,"gradeAnswer":true}],"selectedQuestion":"15"}]}
更新接口代码
@PutMapping("/{id}") Survey update(@RequestBody Survey surveyData, @PathVariable Long id) { return surveyService.findById(id) .map(survey -> { survey.setName(surveyData.getName()); survey.setDescription(surveyData.getDescription()); survey.setSections(surveyData.getSections()); survey.setCreatedBy("Test"); return surveyService.save(survey); }) .orElseGet(() -> surveyService.save(surveyData)); }
SurveyService的save方法仅调用JPA Repository的默认save方法。
错误原因
核心问题是误用同一张关联表survey_section_question维护两组多对多关系:
- Survey与SurveySection的多对多关联
- SurveySection与SurveyQuestion的多对多关联
一张关联表只能对应一组多对多关系,当JPA尝试插入Survey与Section的关联数据时,这张表还需要存储Section与Question的关联字段,导致survey_id字段无法被正确赋值(或表结构本身不兼容),最终触发无默认值的错误。
解决方案
1. 拆分关联表
创建两张独立的关联表:
survey_section:维护Survey与SurveySection的关联,字段为survey_id、section_idsection_question:维护SurveySection与SurveyQuestion的关联,字段为section_id、question_id
2. 修改实体注解
更新Survey类的多对多关联配置:
@ManyToMany(fetch = FetchType.EAGER, cascade = { CascadeType.PERSIST, CascadeType.MERGE }) @JoinTable( name = "survey_section", joinColumns = @JoinColumn(name = "survey_id"), inverseJoinColumns = @JoinColumn(name = "section_id") ) private List<SurveySection> sections;
更新SurveySection类的多对多关联配置:
@ManyToMany @JoinTable( name = "section_question", joinColumns = @JoinColumn(name = "section_id"), inverseJoinColumns = @JoinColumn(name = "question_id") ) private List<SurveyQuestion> questions;
3. 数据库调整
删除原有的survey_section_question表,创建上述两张新关联表。
4. 优化更新逻辑(可选)
更新时传入的sections和questions是游离状态的实体,建议先加载持久化状态的对象再关联,避免额外问题:
survey.setSections(surveyData.getSections().stream() .map(section -> sectionRepository.findById(section.getId()).orElseThrow(() -> new RuntimeException("Section not found"))) .collect(Collectors.toList()));
内容的提问来源于stack exchange,提问作者onner
相关产品推荐
相关产品推荐

