在 ManyToMany 双向映射中,findAll() 获取行,每行包含其子项,而子项又包含其自身

Posted

技术标签:

【中文标题】在 ManyToMany 双向映射中,findAll() 获取行,每行包含其子项,而子项又包含其自身【英文标题】:In a ManyToMany birdirectional mapping findAll() gets rows, each containing its children which in-turn contains itself 【发布时间】:2019-10-18 04:17:23 【问题描述】:

我有如下多对多双向映射的数据模型。

一个产品可以有多个类别,同样的类别可以有多个产品。我正在使用链接表来维护关系。

'Categories'实体定义如下:

@Entity(name = "categories")
class Categories(
        @Id
        @GeneratedValue
        @Column(name="cat_id", unique = true, nullable = false)
        var id: Integer,
        @ManyToMany(fetch = FetchType.LAZY)
        @JoinTable(name = "categories_product", joinColumns = [JoinColumn(name = "cat_id")], inverseJoinColumns = [JoinColumn(name = "prd_id")])
        @JsonIgnoreProperties("productsSet")
        var productsSet: MutableSet<Products>
)

并且“产品”实体有一个列表作为逆映射:

@Entity(name = "products")
class Products(
        @Id
        @GeneratedValue
        @Column(name="prd_id", unique = true, nullable = false)
        var id: Integer,
        @ManyToMany(fetch = FetchType.LAZY, mappedBy = "productsSet")
        @JsonIgnoreProperties("productsSet")
        var categories: MutableSet<Categories>
)

我的映射表“categories_product”有两列“cat_id”和“prd_id”,分别引用了“categories”和“products”表。

我有一个 ProductsRepository 和 CategoriesRepository 实现 CrudRepository。

从 ProductsRepository 的 mappedBy 端调用 findAll() 可以正常工作,如下所示:

[
   
      "id":1,
      "name":"Cricket Bat",
      "price":10.0,
      "categories":[
         
            "id":1,
            "name":"Sports",
            "description":"Sports items"
         
      ]
   ,
   
      "id":2,
      "name":"Spring Boot",
      "price":100.0,
      "categories":[
         
            "id":2,
            "name":"Books",
            "description":"Book items"
         
      ]
   
]

但是,从拥有方即类别调用 findAll() 会返回其所有包含其引用类别的产品,如下所示:

[
   
      "id":1,
      "name":"Sports",
      "description":"Sports items",
      "productsSet":[
         
            "id":1,
            "name":"Cricket Bat",
            "price":10.0,
            "categories":[
               
                  "id":1,
                  "name":"Sports",
                  "description":"Sports items"
               
            ]
         
      ]
   ,
   
      "id":2,
      "name":"Books",
      "description":"Book items",
      "productsSet":[
         
            "id":2,
            "name":"Spring Boot",
            "price":100.0,
            "categories":[
               
                  "id":2,
                  "name":"Books",
                  "description":"Book items"
               
            ]
         
      ]
   
]

如何让拥有方 (CategoriesRepository) 的 findAll() 只返回其子项,而不是映射方 (ProductsRepository) 中的子项?

【问题讨论】:

@JsonIgnoreProperties("productsSet") 替换为@JsonIgnoreProperties("categories")?或者停止在您的 REST API 中使用您的持久性模型,而是使用专门设计的包含您实际希望在 API 中返回的内容的类。 感谢@JBNizet 它有效!是的,我看到了返回专门设计的课程的优势。目前,我需要返回持久性类就足够了。 【参考方案1】:

为了他人的利益,我列出了 cmets 中@JBNizet 给出的解决方案。谢谢,JB 尼泽特!

当使用 @ManyToMany 时,必须包含 @JsonIgnoreProperties 以避免由于递归获取记录而导致 *** 异常。

所以在拥有方定义@JsonIgnoreProperties 来忽略子元素如下:

@ManyToMany(fetch = FetchType.LAZY)
        @JoinTable(name = "categories_product", joinColumns = [JoinColumn(name = "cat_id")], inverseJoinColumns = [JoinColumn(name = "prd_id")])
        @JsonIgnoreProperties("categories")
        var productsSet: MutableSet<Products>

并在映射端定义@JsonIgnoreProperties 忽略父元素如下:

@ManyToMany(fetch = FetchType.LAZY, mappedBy = "productsSet")
        @JsonIgnoreProperties("productsSet")
        var categories: MutableSet<Categories>

【讨论】:

以上是关于在 ManyToMany 双向映射中,findAll() 获取行,每行包含其子项,而子项又包含其自身的主要内容,如果未能解决你的问题,请参考以下文章

关系/对象映射 多对多关系(@ManyToMany 注释)重新认识

JPA中的多对多双向映射

Jpa中ManyToMany和OneToMany的双向控制

Jpa中ManyToMany和OneToMany的双向控制

如何在 Kotlin 中使用 JPA ManyToMany 双向关系

hibernate manytomany 双向