Java 同一类型实体的多对多关系
我有一个实体如下。我很好奇是否有可能建立一种关系,我将用下面的例子来描述:Java 同一类型实体的多对多关系,java,spring,hibernate,many-to-many,bidirectional-relation,Java,Spring,Hibernate,Many To Many,Bidirectional Relation,我有一个实体如下。我很好奇是否有可能建立一种关系,我将用下面的例子来描述: 我正在创建两个个人实体迈克尔和朱莉娅 我要把朱莉娅加入迈克尔的朋友组 之后,我以JSON响应的形式检索Michael,Julia在响应中可用。但当我找回朱莉娅时,她的朋友集是空的。我想通过保存友谊的一面来建立双向的友谊关系。我想让迈克尔在朱莉娅的朋友组里,不用做任何其他的手术。我认为它必须由Hibernate管理。有可能吗?我该怎么做 @ToString(exclude = "friends") // EDIT: th
- 我正在创建两个个人实体迈克尔和朱莉娅
- 我要把朱莉娅加入迈克尔的朋友组
- 之后,我以JSON响应的形式检索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;
} 如果查看hibernate日志,您将看到://创建图形以帮助hibernate使用外部联接创建查询。 @NamedEntityGraph(name=“graph.Person.friends”, attributeNodes=@NamedAttributeNode(value=“friends”)) 类人{} 接口PersonRepository扩展了JpaRepository{ //使用命名图,它将获取同一查询中的所有好友 @凌驾 @EntityGraph(value=“graph.Person.friends”) 完成人员(长id); } @凌驾 公共人物addFriend(字符串personName、字符串friendName) 抛出FriendsExistsException,PersonNotFoundException{ Person-Person=retrieveWithName(personName); Person friend=retrieveWithName(friendName); 如果(!person.getFriends().包含(friend)){ person.getFriends().add(friend); friend.getFriends().add(person);//需要设置关系 return repository.save(person);//只使用一种保存方法,它使用cascade保存好友 }否则{ 抛出新的FriendsExistException(personName、friendName); }
休眠:在person(姓名、id)中插入值(?,)
休眠:在person(姓名、id)中插入值(?,)
Hibernate:在友谊(person\u id,friend\u id)中插入值(?,)
Hibernate:插入友谊(person\u id,friend\u id)值(?,)
您需要手动设置双向关系。比如
。如果你想处理这种关系,不如考虑一个图形数据库。我更喜欢在我的实体内创建一个助手方法,如friend.addFriend(person)和person.addFriend(friend)
,并在那里设置关系,以使代码更可读。@BogdanOros我将以这种方式更新,但我不确定是否应该通过添加到彼此的好友列表来手动进行更新。这表明它是如何工作的。这样做是为了支持数据库中的关系,因为在关系数据库中,您需要有两行来指定此关系。@BogdanOros我知道这一点,并确切地询问这是否可行。我想用一个保存操作在友谊表中插入两行。您将调用makeFriendly(Person)
操作,因为您已经配置了级联,它将自动使用更新的友谊关系保留子集。这正好在以下行中给出stackoverflow错误:save
尝试了相同的示例,没有stackoverflow错误,您可以粘贴stackstrace吗?我刚刚解决了stackoverflow错误。Lombok的toString()、equals()和hashCode()方法导致了它。我排除了friends元素,然后解决了它。现在我在获取一个人时遇到了一个问题。例如,当我获取Julia时,Michael在朋友列表上,它试图获取Michael的朋友列表,它给Julia带来了一个无限循环。这是N+1查询问题,我正在尝试解决它。是的,Lombok无法解析反向引用,这就是我使用DataClass等迁移到Kotlin的原因。对于我在上面提到的问题,您有什么解决建议吗?friend.getFriends()。add(person);
@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); } }
// 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); }