
本文详解 Spring Boot 中更新 API 遇到非空字段(如 DOB)报错的根源与解决方案,并指导如何合并多个 @RequestBody 为单一体,避免参数绑定失败,同时保障数据库约束合规性与业务灵活性。
本文详解 spring boot 中更新 api 遇到非空字段(如 dob)报错的根源与解决方案,并指导如何合并多个 `@requestbody` 为单一体,避免参数绑定失败,同时保障数据库约束合规性与业务灵活性。
在构建 RESTful 更新接口时,常见误区是将“数据库字段 NOT NULL”等同于“API 请求必须传值”。实际上,更新操作应支持部分字段修改——用户仅提交需变更的字段,其余字段保持原值。你遇到的 Column 'dob' cannot be null 错误,本质是:尽管未在 Postman 中发送 dob 字段,但 Spring 默认将缺失字段反序列化为 null,而你的服务层直接调用 setDob(orgPatient.getDob()),将 null 写入数据库,触发 MySQL 的非空约束异常。
✅ 正确做法:空值跳过更新(推荐)
在 Service 层显式判断字段是否为 null,仅对非空字段执行赋值:
if (orgPatient.getFirstName() != null) updatedUser.setFirstName(orgPatient.getFirstName());
if (orgPatient.getMiddleName() != null) updatedUser.setMiddleName(orgPatient.getMiddleName());
if (orgPatient.getLastName() != null) updatedUser.setLastName(orgPatient.getLastName());
if (orgPatient.getDob() != null) updatedUser.setDob(orgPatient.getDob()); // ← 关键修复
if (orgPatient.getGender() != null) updatedUser.setGender(orgPatient.getGender());
if (patientContact.getContactNumberType() != null)
updatedContactUser.setContactNumberType(patientContact.getContactNumberType());
if (patientContact.getContactNumer() != null)
updatedContactUser.setContactNumer(patientContact.getContactNumer());
if (patientContact.getContactAreaCode() != null)
updatedContactUser.setContactAreaCode(patientContact.getContactAreaCode());
? 提示:可进一步封装为工具方法(如
BeanUtils.copyNonNullProperties(src, target)),或使用 MapStruct 的@Mapping(target = "dob", ignore = true)+ 自定义 setter 逻辑。
❌ 禁止写法:多 @RequestBody 同时存在
Spring MVC 不支持一个请求中绑定多个 @RequestBody。你当前的 Controller 声明:
@PutMapping("/update/{PatientId}")
public ResponseEntity<string> updateOrg(
@PathVariable String PatientId,
@RequestBody OrgPatient orgPatient, // ← 第一个 @RequestBody(合法)
@RequestBody PatientContact patientContact // ← 第二个 @RequestBody(非法!)
)</string>
会导致启动失败或运行时 HttpMessageNotReadableException。HTTP 请求体只有一个,无法被两个注解同时消费。
✅ 正确方案:定义统一 DTO 封装多实体数据
创建一个聚合 DTO,将两个实体字段整合为单个 JSON 结构:
public class PatientUpdateRequest {
private OrgPatient orgPatient;
private PatientContact patientContact;
// getters & setters
}
Controller 改为接收该 DTO:
@PutMapping("/update/{PatientId}")
public ResponseEntity<string> updateOrg(
@PathVariable String PatientId,
@RequestBody PatientUpdateRequest request) { // ← 单一、清晰的请求体
String ans = updateOrgPatientService.updateOrgColumn(
PatientId,
request.getOrgPatient(),
request.getPatientContact()
);
return ResponseEntity.ok(ans);
}</string>
Postman 中发送如下 JSON(仅含需更新的字段):
{
"orgPatient": {
"firstName": "John",
"gender": "MALE"
},
"patientContact": {
"contactNumer": "123-456-7890"
}
}
? 补充建议:增强健壮性
-
数据库层面:若
dob允许为空(业务上确实可能未知),建议将表字段改为NULL(ALTER TABLE org_patient MODIFY dob DATE NULL;),再配合 Java 层LocalDate类型与@Nullable注解。 -
校验层面:使用
@Valid+ 自定义@PatchValid注解,对必填更新字段做前置校验(如 ID 不可为空),返回400 Bad Request而非 500。 -
事务保障:为
updateColumn()方法添加@Transactional,确保两表更新原子性,避免部分成功导致数据不一致。
通过以上重构,你将获得一个符合 REST 规范、兼容部分更新语义、结构清晰且生产就绪的更新 API。










