在 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 注释)重新认识