Spring Data JPA:保存嵌套的 OneToMany 子级(具有级联)返回 NULL 父级外部对象
Posted
技术标签:
【中文标题】Spring Data JPA:保存嵌套的 OneToMany 子级(具有级联)返回 NULL 父级外部对象【英文标题】:Spring Data JPA: Saving nested OneToMany children (with cascading) returns NULL parent foreign object 【发布时间】:2020-08-27 12:27:17 【问题描述】:我有两个模型对象:父对象和子对象。模型类如下:
import javax.persistence.*
@Entity
@Table(name = "parents")
class Parent(
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
val id: Int? = 0,
val name: String? = "",
val age: Int? = null,
@OneToMany(cascade = [CascadeType.MERGE])
@JoinColumn(name = "parent_id")
val children: List<Child>?= mutableListOf()
)
import com.fasterxml.jackson.annotation.JsonIgnoreProperties
import javax.persistence.*
@Entity
@Table(name = "children")
class Child(
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
val id: Int? = 0,
val name: String? = "",
val age: Int? = null,
@ManyToOne
@JsonIgnoreProperties(value = ["name", "age", "children"], allowSetters = true)
val parent: Parent?
)
在父对象中有一个名为“Children”的属性,它接受一组子对象。此子属性具有 @OneToMany 注释,级联设置为 CascadeType.MERGE。它还具有 @JoinColumn 注释,名称参数设置为“parent_id”
在 Child 对象中,“parent”属性具有 @ManyToOne 注释以及 @JsonIgnoreProperties 注释,其中其值设置为“children”。这用于禁止在 Jackson 序列化时发生无限递归循环。
我面临的问题是通过路由保存父对象(在数组中包含嵌套的子对象)。所以当我保存一个像这样的父对象时:
"name": "Tom's Dad",
"age": 55,
"children": [
"name": "Tom",
"age": 20
,
"name": "Jerry",
"age": 22
]
我得到以下 JSON 保存结果:
"id": 10,
"name": "Tom's Dad",
"age": 55,
"children": [
"id": 19,
"name": "Tom",
"age": 20,
"parent": null
,
"id": 20,
"name": "Jerry",
"age": 22,
"parent": null
]
请注意,在嵌套子列表中,外部父对象为 NULL。这个结果的问题出现在我正在使用的前端 Angular 应用程序中。 Angular 应用程序将返回的 Parent 对象与嵌套的子对象一起保存,其中 parent 外部属性设置为 null。所以如果我重新保存或更新Parent对象,数据库中的foreign_key设置为NULL,这些父对象和子对象之间的关系就终止了。
我想知道有没有办法在保存父对象时,返回的子对象将具有父对象,如下所示:
"id": 10,
"name": "Tom's Dad",
"age": 55,
"children": [
"id": 19,
"name": "Tom",
"age": 20,
"parent":
"id": 10
,
"id": 20,
"name": "Jerry",
"age": 22,
"parent":
"id": 10
]
编辑:
这是控制器类。为了简化目的,重新创建了整个示例。所以没有使用服务类。
package com.example.parentchild
import org.springframework.web.bind.annotation.*
@RestController
@CrossOrigin
class Route(val parentRepo: ParentRepo)
@PostMapping("/parent/save")
fun saveParent(@RequestBody parent: Parent) = this.parentRepo.save(parent)
@GetMapping("/parent/all")
fun getAllParents() = this.parentRepo.findAll()
@GetMapping("/parent/id")
fun getAllParents(@PathVariable id: Int) = this.parentRepo.findById(id).get()
【问题讨论】:
你一定需要子列表中的父对象吗? 我知道你的意思。但为了方便起见,我需要它。我不需要整个父对象,我需要的只是每个父对象只有 id。因此,您可以看到我添加了一个注释 @JsonIgnoreProperties,其中我添加了除 id 之外的父类的所有属性。 当然,在重新保存父对象时,我可以从前端应用程序手动将 id 手动放入子对象的父属性中,但这是我一直试图避免的。 【参考方案1】:你能把控制器和服务代码复制粘贴到这里吗?
【讨论】:
以上是关于Spring Data JPA:保存嵌套的 OneToMany 子级(具有级联)返回 NULL 父级外部对象的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 spring4+spring-data-jpa(hibernateJpaVendorAdapter)+multidatasource+one entityManager+jpaReposit
使用Spring Data JPA查询时,报result returns more than one elements异常
spring-data-jpa——如果使用了one-to-many,many-to-one的注解,在Jackson进行json字符串化时出现错误的解决方案