Spring Boot+Hibernate一对多关联增改数据触发MySQL非空约束异常
搞定Spring Boot + Hibernate一对多关联的非空约束异常
嘿,我来帮你解决这个头疼的数据库约束异常问题!你遇到的两个报错本质都是数据库的非空约束没被满足,咱们一步步拆解解决:
先搞懂为啥报错
- 操作
Company时提示Column 'activity' cannot be null:说明你的数据库里activity列设置了NOT NULL,但你保存或更新Company的时候,这个字段没赋值,是空的。 - 操作
Contact时提示Column 'fk_company' cannot be null:因为Contact和Company是一对多的关联关系,Contact属于某个Company,数据库里fk_company这个外键列设置了非空,但你保存Contact时没把它和对应的Company关联起来。
分步解决问题
1. 解决Company的activity字段非空问题
先核对两个地方:
- 看看你的
Company实体类,activity字段有没有加@Column(nullable = false)(如果数据库里这个列是NOT NULL,实体类最好对应上,避免混淆)。 - 保存/更新
Company之前,一定要给activity赋值,比如:
Company myCompany = new Company(); myCompany.setActivity("企业管理咨询"); // 这里必须给个有效值,不能留空 companyRepo.save(myCompany);
如果业务上这个字段是可选的,那你得修改数据库表结构,把activity列的NOT NULL约束去掉,同时实体类里把@Column(nullable = false)改成nullable = true(或者直接删掉这个注解,默认就是允许空)。
2. 解决Contact的fk_company非空问题
一对多关联里,Contact是“多方”,必须绑定到一个Company上(因为外键非空),所以要把关联关系维护好:
第一步:检查实体类的关联配置是否正确
正确的双向一对多配置应该是这样的(补全你之前没写完的代码):
// Company 实体(一对多的一方) @Entity public class Company { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; // 对应数据库的activity列,如果非空就加nullable=false @Column(nullable = false) private String activity; // 一对多关联,mappedBy指定多方的关联字段是company,级联操作方便批量处理 @OneToMany(mappedBy = "company", cascade = CascadeType.ALL, orphanRemoval = true) private List<Contact> contacts = new ArrayList<>(); // 一定要加这个辅助方法,用来维护双向关联的一致性 public void addContact(Contact contact) { contacts.add(contact); contact.setCompany(this); // 关键!这里会自动把Contact和当前Company绑定 } // 省略getter和setter } // Contact 实体(多对一的多方) @Entity public class Contact { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name; // 多对一关联,optional=false对应数据库外键非空 @ManyToOne(optional = false) @JoinColumn(name = "fk_company") // 对应数据库的外键列名 private Company company; // 省略getter和setter }
第二步:保存Contact的正确姿势
有两种靠谱的方式:
- 方式一:通过Company的辅助方法添加Contact,然后保存Company(利用级联保存,省心)
// 先从数据库取出要关联的Company Company targetCompany = companyRepo.findById(1L) .orElseThrow(() -> new RuntimeException("找不到对应的Company哦")); Contact newContact = new Contact(); newContact.setName("王五"); targetCompany.addContact(newContact); // 这里自动绑定了Contact和Company companyRepo.save(targetCompany); // 级联保存Contact
- 方式二:直接给Contact设置Company,然后单独保存Contact
Company targetCompany = companyRepo.findById(1L) .orElseThrow(() -> new RuntimeException("找不到对应的Company哦")); Contact newContact = new Contact(); newContact.setName("赵六"); newContact.setCompany(targetCompany); // 必须手动设置,不能留空 contactRepo.save(newContact);
如果业务上允许Contact不关联任何Company,那你得修改数据库表的fk_company列,去掉NOT NULL约束,同时把Contact实体类里的@ManyToOne(optional = false)改成optional = true。
额外小技巧
要是还搞不清问题出在哪,可以打开Hibernate的SQL日志,看看实际执行的SQL语句,一眼就能发现哪个字段没赋值:
在application.properties里加这两行:
spring.jpa.show-sql=true spring.jpa.properties.hibernate.format_sql=true
内容的提问来源于stack exchange,提问作者sihamxxi
相关产品推荐
相关产品推荐

