简体   繁体   English

如何使双方多对多关系船东?

[英]How make both sides of many-to-many relation ships owner?

I have a class Group and a class User我有一个班级Group和一个班级User
where Group and User are many-to-many relation ship其中 Group 和 User 是多对多关系
If i change the groups of a user and save a user i want to update the groups如果我更改usergroups并保存user我想更新groups
and vice versa where if i changed a user of a group and save the group i want the user to be updated反之亦然,如果我更改了groupuser并保存了group我希望user更新
Do i have to set the mappedBy in both classes我是否必须在两个类中都设置mappedBy
Note : I am using eclipseLink注意:我正在使用eclipseLink

For a many-to-many relationship, you will need to update the relationship data on both sides in order to stay consistent.对于多对多关系,您需要更新双方的关系数据以保持一致。

Unfortunately there is no shortcut.不幸的是,没有捷径可走。

What you can do is to create a single method on either of the entities or a third class to encapsulate the consistent update.您可以做的是在实体或第三个类中创建一个方法来封装一致的更新。

Beware of infinite loops - do not implement the propagation to the other entity in both entity classes.当心无限循环 - 不要在两个实体类中实现到另一个实体的传播。

Roughly like this:大致是这样的:

public class User
...
public void addGroup(Group g){
   groups.add(g);
   g.addUser(this);
}

or

public class Group
...
public void addUser(User u){
   users.add(u);
   u.addGroup(this);
}

I assume the presence of proper cascade settings on the relationship annotations.我假设关系注释上存在适当的级联设置。

There is a difference between owning a relation and a bidirectional reference .拥有关系双向引用是有区别的。 The former primarily concerns the layout of your database where the latter concerns your application logic.前者主要涉及数据库的布局,后者涉及应用程序逻辑。 From your question, I assume that you want the latter.从你的问题来看,我假设你想要后者。 At the same time, it is generally recommendable that only one side of a relation owns a reference.同时,通常建议只有关系的一侧拥有引用。 You can easily create a bidirectional reference while keeping a clear collection owner by creating add and remove methods that enforce bidrection:通过创建强制执行bidrection的add和remove方法,您可以轻松创建双向引用,同时保持明确的集合所有者:

class Group {

  @ManyToMany
  private Collection<User> users = ... ;

  public void addUser(User user) {
    if(user != null && !users.contains(user)) {
      users.add(user)
      user.addGroup(this);
    }
  }

  public void removeUser(User user) {
    if(user != null && users.contains(user)) {
      users.remove(user)
      user.removeGroup(this);
    }
  }
}

class User {

  @ManyToMany(mappedBy="users")
  private Collection<Group> groups = ... ;

  public void addGroup(Group group) {
    if(group != null && !groups.contains(group)) {
      groups.add(group)
      group.addUser(this);
    }
  }

  public void removeGroup(Group group) {
    if(group != null && groups.contains(group)) {
      groups.remove(group)
      group.removeUser(this);
    }
  }
}

In this example, Group owns the relation what does however not affect the application logic.在此示例中, Group拥有关系,但不会影响应用程序逻辑。 Be aware of the manipulation order in order to avoid infinite loops.注意操作顺序以避免无限循环。 Also, note that this code is not thread-safe.另请注意,此代码不是线程安全的。

I understand that for author it is a little bit late, but maybe it will be helpful for another readers.我知道对作者来说有点晚了,但也许它会对其他读者有所帮助。

You can achieve this by adding @JoinTable for both sides: (cascading you can add by your needs)您可以通过为双方添加@JoinTable 来实现这一点:(您可以根据需要添加级联)

public class Group {
    ....

    @ManyToMany
    @JoinTable(
            name = "group_user", 
            joinColumns = @JoinColumn(name = "groups_id"),
            inverseJoinColumns = @JoinColumn(name = "users_id"))
    private List<User> users;
}
public class User {
    ....

    @ManyToMany
    @JoinTable(
            name = "group_user", 
            joinColumns = @JoinColumn(name = "users_id"),
            inverseJoinColumns = @JoinColumn(name = "groups_id"))
    private List<Group> groups;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM