Spring Data REST如何单请求创建带关联的JPA实体
单次请求创建带关联JPA实体的实现方案
实体基础配置说明
涉及的关联JPA实体定义如下:
@Entity @Table(name = "distributor") class Distributor : AbstractEntity<Long>() { @Column(nullable = false) val name: String? = null @OneToMany(mappedBy = "distributor", cascade = [CascadeType.ALL]) @RestResource var managers: MutableList<DistributionManager>? = null @OneToMany(mappedBy = "distributor") var catalog: MutableList<Good> = mutableListOf() } @Entity @Table(name = "distribution_manager") class DistributionManager : AbstractPersonEntity<Long>() { @ManyToOne @JoinColumn(name = "distributor_id") var distributor: Distributor? = null }
上述实体为存在一对多/多对一关联的经销商(Distributor)、分销经理(DistributionManager)JPA实体,默认流程下创建带关联的Distributor需要3次请求:先创建Distributor实体,再创建DistributionManager实体,最后绑定二者关联,操作繁琐。
前置依赖条件
现有代码已经满足单次请求创建的核心要求:
- Distributor实体的
managers字段配置了CascadeType.ALL,支持级联持久化、更新关联的DistributionManager实体 managers字段添加了@RestResource注解,暴露了关联操作权限,不需要额外修改Repository层配置
请求构造方式
直接向Distributor对应的集合资源接口(默认路径为/distributors,如果配置了全局rest基础路径则拼接对应前缀)发起POST请求,请求体中直接嵌套传入managers关联的对象列表即可。
注意:Distributor实体的catalog关联字段未配置级联持久化规则,请求体中不要传入该字段,否则会触发关联实体未持久化报错。
示例请求如下:
POST /distributors HTTP/1.1 Content-Type: application/json { "name": "华东区域总经销商", "managers": [ { "firstName": "王", "lastName": "五", // 传入DistributionManager实体所有自有业务字段,继承自AbstractPersonEntity的属性均在此处赋值 "phone": "13xxxxxxxxx" }, { "firstName": "赵", "lastName": "六", "phone": "13xxxxxxxxx" } ] }
常见问题处理
如果你的DistributionManager实体中distributor关联字段配置了非空约束(@JoinColumn(name = "distributor_id", nullable = false)),直接发起上述请求可能触发外键约束报错,原因是双向关联下JPA不会自动为嵌套保存的子实体设置反向关联引用。
解决方式是在Distributor实体类中添加JPA生命周期回调方法,在持久化、更新前自动同步反向关联:
@PrePersist @PreUpdate fun syncManagerAssociation() { managers?.forEach { it.distributor = this } }
添加该方法后,单次请求会自动完成Distributor创建、关联DistributionManager批量创建、二者关联关系绑定全流程,无需拆分多次请求。
内容的提问来源于stack exchange,提问作者clumerze
相关产品推荐
相关产品推荐

