使用IDEA Buddy开发Spring Data JPA+Rest Repositories时Project实体manager非空报错
报错原因
这个报错是Spring Data REST处理关联对象的默认逻辑和JPA持久化约束冲突导致的,具体原因如下:
- 你在
Project实体的manager字段上配置了@ManyToOne(optional = false)非空约束,要求该属性必须指向一个已经被JPA持久化上下文管理的实体,不能为null也不能是未持久化的瞬时态对象。 - Spring Data REST默认不支持直接通过嵌套JSON对象的
id自动关联已有的持久化实体,你提交的JSON里manager是仅带id的嵌套对象,Spring Data REST会将其解析为一个没有被持久化的瞬时态AppUser实例,而非数据库中id为1的已有AppUser实体,JPA校验时就会触发非空约束报错。
解决方案
可以根据你的使用场景选择以下任意一种方案:
方案1:使用Spring Data REST标准的关联资源URI提交(推荐)
Spring Data REST默认要求关联资源用对应的资源URI作为值,不需要嵌套对象,修改提交的JSON结构即可:
{ "name":"deoakw12", "manager": "/appUsers/1", "tasks":[ { "name":"oooo", "assignee": "/appUsers/2" }, { "name":"oooo1", "assignee": "/appUsers/2" } ] }
Spring Data REST会自动根据URI查询到对应的持久化实体赋值,不需要额外修改代码。
方案2:配置JSON序列化支持嵌套id关联
如果需要保留嵌套对象传id的提交方式,可以给AppUser实体类添加@JsonIdentityInfo注解,让Jackson反序列化时自动根据id绑定实体:
import com.fasterxml.jackson.annotation.JsonIdentityInfo; import com.fasterxml.jackson.annotation.ObjectIdGenerators; @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id") @Entity public class AppUser { // 原有实体逻辑 }
配置完成后提交原来的嵌套id格式的JSON即可正常解析。
方案3:自定义反序列化逻辑
如果上面的方案不满足需求,可以自定义Jackson反序列化器,在反序列化manager属性时,根据传入的id主动从AppUserRepository查询对应的持久化实例赋值即可。
注意:无论使用哪种方案,都需要提前确认数据库中id为1的
AppUser、id为2的assignee对应实体确实存在,避免因为实体不存在导致赋值为null触发同样的报错。
内容的提问来源于stack exchange,提问作者dean gao
相关产品推荐
相关产品推荐

