同一类型实体的多对多关系
Many to many relationship for same type entity
我有一个实体如下。我很好奇是否可以建立关系,正如我将在示例中描述的那样:
- 我正在创建 2 个 Person 实体 Michael 和 Julia.
- 我正在将 Julia 添加到 Michael 的好友集中。
之后,我将检索 Michael 作为 JSON 响应,Julia 在响应中可用。但是当我检索 Julia 时,她的朋友集是空的。我想通过只保存友谊的一侧来建立双向友谊关系。我想在不做任何其他操作的情况下让 Michael 进入 Julia 的朋友组。我认为它必须由 Hibernate 管理。这可能吗?我应该怎么做?
@ToString(exclude = "friends") // EDIT: these 2 exclusion necessary
@EqualsAndHashCode(exclude = "friends")
public class Person{
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id")
private Long id;
@Column(name = "name",unique = true)
private String name;
@JsonIgnoreProperties("friends") // EDIT: will prevent the infinite recursion
@ManyToMany(cascade = CascadeType.ALL)
@JoinTable(name = "FRIENDSHIP",
joinColumns = @JoinColumn(name = "person_id",
referencedColumnName = "id"),
inverseJoinColumns = @JoinColumn(name = "friend_id",
referencedColumnName = "id"))
private Set<Person> friends;
下面是我创建友谊的服务层代码:
@Override
public Person addFriend(String personName, String friendName)
throws FriendshipExistsException, PersonNotFoundException {
Person person = retrieveWithName(personName);
Person friend = retrieveWithName(friendName);
if(!person.getFriends().contains(friend)){
person.getFriends().add(friend);
return repository.save(person);
}
else{
throw new FriendshipExistsException(personName, friendName);
}
}
Related Question:
Updated the source code and this version is working properly.
// Creating a graph to help hibernate to create a query with outer join.
@NamedEntityGraph(name="graph.Person.friends",
attributeNodes = @NamedAttributeNode(value = "friends"))
class Person {}
interface PersonRepository extends JpaRepository<Person, Long> {
// using the named graph, it will fetch all friends in same query
@Override
@EntityGraph(value="graph.Person.friends")
Person findOne(Long id);
}
@Override
public Person addFriend(String personName, String friendName)
throws FriendshipExistsException, PersonNotFoundException {
Person person = retrieveWithName(personName);
Person friend = retrieveWithName(friendName);
if(!person.getFriends().contains(friend)){
person.getFriends().add(friend);
friend.getFriends().add(person); // need to setup the relation
return repository.save(person); // only one save method is used, it saves friends with cascade
} else {
throw new FriendshipExistsException(personName, friendName);
}
}
如果您检查休眠日志,您将看到:
Hibernate:插入 person (name, id) 值 (?, ?)
Hibernate:插入 person (name, id) 值 (?, ?)
休眠:插入友谊(person_id,friend_id)值(?,?)
休眠:插入友谊(person_id,friend_id)值(?,?)
我有一个实体如下。我很好奇是否可以建立关系,正如我将在示例中描述的那样:
- 我正在创建 2 个 Person 实体 Michael 和 Julia.
- 我正在将 Julia 添加到 Michael 的好友集中。
之后,我将检索 Michael 作为 JSON 响应,Julia 在响应中可用。但是当我检索 Julia 时,她的朋友集是空的。我想通过只保存友谊的一侧来建立双向友谊关系。我想在不做任何其他操作的情况下让 Michael 进入 Julia 的朋友组。我认为它必须由 Hibernate 管理。这可能吗?我应该怎么做?
@ToString(exclude = "friends") // EDIT: these 2 exclusion necessary @EqualsAndHashCode(exclude = "friends") public class Person{ @Id @GeneratedValue(strategy = GenerationType.AUTO) @Column(name = "id") private Long id; @Column(name = "name",unique = true) private String name; @JsonIgnoreProperties("friends") // EDIT: will prevent the infinite recursion @ManyToMany(cascade = CascadeType.ALL) @JoinTable(name = "FRIENDSHIP", joinColumns = @JoinColumn(name = "person_id", referencedColumnName = "id"), inverseJoinColumns = @JoinColumn(name = "friend_id", referencedColumnName = "id")) private Set<Person> friends;
下面是我创建友谊的服务层代码:
@Override
public Person addFriend(String personName, String friendName)
throws FriendshipExistsException, PersonNotFoundException {
Person person = retrieveWithName(personName);
Person friend = retrieveWithName(friendName);
if(!person.getFriends().contains(friend)){
person.getFriends().add(friend);
return repository.save(person);
}
else{
throw new FriendshipExistsException(personName, friendName);
}
}
Related Question:
Updated the source code and this version is working properly.
// Creating a graph to help hibernate to create a query with outer join.
@NamedEntityGraph(name="graph.Person.friends",
attributeNodes = @NamedAttributeNode(value = "friends"))
class Person {}
interface PersonRepository extends JpaRepository<Person, Long> {
// using the named graph, it will fetch all friends in same query
@Override
@EntityGraph(value="graph.Person.friends")
Person findOne(Long id);
}
@Override
public Person addFriend(String personName, String friendName)
throws FriendshipExistsException, PersonNotFoundException {
Person person = retrieveWithName(personName);
Person friend = retrieveWithName(friendName);
if(!person.getFriends().contains(friend)){
person.getFriends().add(friend);
friend.getFriends().add(person); // need to setup the relation
return repository.save(person); // only one save method is used, it saves friends with cascade
} else {
throw new FriendshipExistsException(personName, friendName);
}
}
如果您检查休眠日志,您将看到:
Hibernate:插入 person (name, id) 值 (?, ?)
Hibernate:插入 person (name, id) 值 (?, ?)
休眠:插入友谊(person_id,friend_id)值(?,?)
休眠:插入友谊(person_id,friend_id)值(?,?)