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字符串化时出现错误的解决方案

Spring data jpa嵌套事务回滚不删除插入?

在为嵌套对象创建自定义 Spring Data JPA 查询时获取 IllegalArgumentException

spring-data-jpa循环保存数据,为啥只保存了最后一条数据