同一类型实体的多对多关系

时间:2018-01-31 21:08:42

标签: java spring hibernate many-to-many bidirectional-relation

我有一个实体如下。我很好奇是否有可能创建一个关系,我将用示例描述:

  • 我正在创建2个实体 Michael Julia
  • 我正在将朱莉娅添加到迈克尔的朋友那里。
  • 之后我将Michael视为JSON响应,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);
    }
}
  

相关问题:   N+1 query on bidirectional many to many for same entity type

     

更新了源代码,此版本正常运行。

1 个答案:

答案 0 :(得分:1)

// 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:插入人(姓名,id)值(?,?)
Hibernate:插入人(姓名,id)值(?,?)
Hibernate:插入友谊(person_id,friend_id)值(?,?)
Hibernate:插入友谊(person_id,friend_id)值(?,?)