我在使用Spring Data JPA和Hibernate作为JPA提供程序的多对多双向Map方面遇到了麻烦。双向关系Map允许您在两个方向上导航关联,这正是我所需要的。我有两个实体:Artist
和Song
。当我得到一个艺术家,我想得到他所有的歌曲,反之亦然,当我得到一首歌,我想得到这首歌的艺术家。这会导致一个递归错误,正如我所研究的那样,可以使用@JsonIdentityInfo或@JsonIgnore解决,但如果它们没有给予我真正想要的JSON,就不会解决。
艺术家实体:
@Entity
@Table(name = "artist")
@JsonIdentityInfo(
generator = ObjectIdGenerators.PropertyGenerator.class,
property = "id")
public class Artist {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
@Column(name = "name")
private String name;
@Column(name = "image")
private String image;
@ManyToMany(fetch = FetchType.LAZY, cascade = { CascadeType.PERSIST, CascadeType.MERGE })
@JoinTable(name = "artist_songs", joinColumns = { @JoinColumn(name = "artist_id") }, inverseJoinColumns = {
@JoinColumn(name = "song_id") })
private Set<Song> songs = new HashSet<>();
}
歌曲实体:
@Entity
@Table(name = "song")
@JsonIdentityInfo(
generator = ObjectIdGenerators.PropertyGenerator.class,
property = "id")
public class Song {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
@Column(name = "title")
private String title;
@Column(name = "src")
private String src;
@Column(name = "image")
private String image;
@ManyToMany(fetch = FetchType.LAZY,
cascade = {
CascadeType.PERSIST,
CascadeType.MERGE
},
mappedBy = "songs")
private Set<Artist> artists = new HashSet<>();
}
我的问题是,当我调用这些实体时,我得到了这些JSON对象:
// THE JSON I GET WHEN I CALL http://localhost:8080/api/artists
[
{
"id": 1,
"name": "artist1",
"image": "artist1.png",
"songs": [
{
"id": 1,
"title": "song 1",
"src": "spng1.mp3",
"image": "song1.png",
"artists": [
1
]
},
{
"id": 2,
"title": "song 2",
"src": "song2.mp3",
"image": "song2.png",
"artists": [
1
]
}
]
},
{
"id": 2,
"name": "artist2",
"image": "artist2.png",
"songs": [
{
"id": 3,
"title": "song 3",
"src": "song3.mp3",
"image": "song3.png",
"artists": [
2
]
}
]
}
]
// THE JSON I GET WHEN I CALL http://localhost:8080/api/songs
[
{
"id": 1,
"title": "song 1",
"src": "spng1.mp3",
"image": "song1.png",
"artists": [
{
"id": 1,
"name": "artist1",
"image": "artist1.png",
"songs": [
{
"id": 2,
"title": "song 2",
"src": "song2.mp3",
"image": "song2.png",
"artists": [
1
]
},
1
]
}
]
},
2,
{
"id": 3,
"title": "song 3",
"src": "song3.mp3",
"image": "song3.png",
"artists": [
{
"id": 2,
"name": "artist2",
"image": "artist2.png",
"songs": [
3
]
}
]
}
]
我想要的JSON对象是这样的:
// THE ARTIST ENTITY
{
"id": 2,
"name": "artist2",
"image": "artist2.png",
"songs": [
{
"id": 1,
"title": "song 1",
"src": "song1.mp3",
"image": "song1.png",
//REMOVES THE FIELD artists INSIDE SONG. KEEPS THAT FIELD ONLY WHEN I MAKE THE CALL TO GET ALL SONGS
},
{
"id": 2,
"title": "song 2",
"src": "song2.mp3",
"image": "song2.png",
//REMOVES THE FIELD artists INSIDE SONG. KEEPS THAT FIELD ONLY WHEN I MAKE THE CALL TO GET ALL SONGS
}
]
}
// THE SONG ENTITY
{
"id": 1,
"title": "song 1",
"src": "song1.mp3",
"image": "song1.png",
"artists": [
{
"id": 2,
"name": "artist2",
"image": "artist2.png",
//REMOVES THE FIELD songs INSIDE ARTIST. KEEPS THAT FIELD ONLY WHEN I MAKE THE CALL TO GET ALL ARTISTS
}
]
}
1条答案
按热度按时间zkure5ic1#
您正在查找的Jackson注解是
@JsonManagedReference
和@JsonBackReference
的组合。你可以把它放在关系的两端。但是,它只能用于 * 一对一 、 一对多 * 和 * 多对一 * 关系。不是“多对多”。这就是为什么你应该在结构上将你的双向 * 多对多 * 关系分解为两个 * 多对一 * 关系(正如@Rogue的评论中所建议的那样)。
这是完整的解决方案
首先我们定义一个复合键类:
使用这个复合键类,我们将创建实体类,它对连接表进行建模:
在此之后,我们可以在Artist和Song实体中配置反向引用:
请注意添加的Jackson注解,它应该修复递归错误,并提供JSON对象的所需布局。
基于:https://www.baeldung.com/jpa-many-to-many