Axios POST传React对象到Spring Boot时字段为空、主键重复报错
问题根因与解决方案
你遇到的是前后端联调Spring Boot JPA持久化的两个典型问题,分别对应排查过程的两个阶段:
第一阶段:请求反序列化后title为null
这个问题你已定位到根因:
- 前端Axios写法
post(url, {book})是ES6对象简写语法,实际发出的请求体是{"book":{/* 图书字段 */}}嵌套结构,但后端接口用@RequestBody Book接收时,会直接将请求体最外层的属性映射到Book实体字段,也就是找最外层的title、authorID等字段,所有字段被嵌套在book属性下时,反序列化后外层字段全为null,就会触发数据库非空约束报错。你修正请求体直接传图书字段后该问题已解决。
第二阶段:主键重复报错Duplicate entry '52' for key 'book.PRIMARY'
哪怕配置了@GeneratedValue仍报这个错,通常是两类原因导致:
- 主键生成策略配置问题:
GenerationType.AUTO会让Hibernate自动选择主键生成方式,MySQL环境下默认可能选择基于单独序列表的生成策略,不会读取业务表实际的最大主键值,一旦序列表记录的下一个可分配ID小于业务表现有最大主键,就会生成重复ID触发冲突。 - 传入实体带非空主键值:Spring Data JPA的
save()方法逻辑为「传入实体主键为空则走新增、自动生成ID;传入实体主键非空则默认按更新逻辑处理」,如果前端传的book对象里携带了已存在的bookID值,就会绕过自动ID生成逻辑,直接用传入的ID执行持久化,撞上已存在的主键就会报错。
可直接落地的修复步骤
- 先检查前端提交的请求体,确认
bookID字段为null或未被包含在请求参数中,不要给新增接口传非空的主键值。 - 将Book实体类的主键生成策略从
AUTO改为明确依赖数据库自增的IDENTITY策略,避免序列表和实际表数据不一致的问题,注解写法参考:
@Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long bookID;
- 改完实体类后如果仍报错,手动同步数据库表的自增起始值,执行以下SQL即可:
-- 先查询当前表内最大主键值 SELECT MAX(bookID) FROM book; -- 假设查询到最大ID为52,将自增起始值调整为比最大值大1即可 ALTER TABLE book AUTO_INCREMENT = 53;
- 最后做基础校验:确认Book实体的bookID字段类型和数据库主键类型匹配(推荐用
Long不要用int,避免数值溢出)、实体类没有给bookID写死默认值、数据库主键约束确实配置在bookID字段上。
内容的提问来源于stack exchange,提问作者TeaDrinker
相关产品推荐
相关产品推荐

