简体   繁体   中英

Updating ManyToMany relationships in JPA or Hibernate

I have two Entity like below...

@Entity
@Table(name = "USER")
public class User {
    @Id
    private Long id;

    private String name;

    @ManyToMany(fetch = FetchType.LAZY, mappedBy = "groupMemberList")
    @Fetch(FetchMode.SELECT)
    private List<Group> groupList = new ArrayList<>();

    // Getters - Setters
}


@Entity
@Table(name = "GROUP")
public class Group {
    @Id
    private Long id;

    private String name;

    @ManyToMany(fetch = FetchType.LAZY/*, mappedBy = "groupList"*/)
    @Fetch(FetchMode.SELECT)
    @JoinTable(name = "SEC_GROUP_VS_MEMBER", joinColumns = @JoinColumn(name = "GROUP_ID"),
            inverseJoinColumns = @JoinColumn(name = "MEMBER_ID"))
    private List<User> groupMemberList;

    // Getters - Setters
}

I want to update the User sometimes and also Group sometimes with the methods below...

Method#1

public boolean updateGroup(Long groupId, List<Staff> groupMemberList) {
    Group group = hibernateTemplate.get(Group.class, groupId);

    group.setGroupMemberList(groupMemberList);
    hibernateTemplate.merge(group); // Group updated with the users
    return true;
}

Method#2

public boolean updateUser(Long userId, List<Group> groupList) {
    User user = hibernateTemplate.get(User.class, userId);

    user.setGroupList(groupList);
    hibernateTemplate.merge(user); // User not updated with the groups
    return true;
}

The first method works fine but not the second one. BUT when I move the join table from Group.class to User.class then second method works fine and not the first one.

The issue is an Owning Entity issue.

Assuming that Staff is a subclass of User , your issue is that only one side of the relationship is the owning entity. The mappedBy = "groupMemberList" makes the Group entity the owning entity and so only changes to that entity are persisted. This means that you have to update the groupMemberList in the Group entity in both cases. If you have a list of groups for a User then you have to iterate over the list of groups and add the User to it. The groupList in User is only for retrieval.

Given User and GroupMember entities:

@Entity
public class User {
    @Id @GeneratedValue
    private Long id;

    @ManyToMany(mappedBy = "groupMemberList")
    private List<GroupMember> groupList;

@Entity
public class GroupMember {
    @Id @GeneratedValue
    private Long id;

    @ManyToMany
    private List<User> groupMemberList;

Then:

// create starting user and membergroup    
tx.begin();
User user = new User();
em.persist(user);
GroupMember group = new GroupMember();
em.persist(group);
tx.commit();
em.clear();

// update users for groupId 2
System.out.println("update users for groupId 2");
tx.begin();
List<User> users = new ArrayList<>();
users.add(user);
group.setGroupMemberList(users);
em.merge(group);            
tx.commit();
em.clear();

// update groups for userId 1 -- doesn't work, not owner of relationship
System.out.println("update groups for userId 1 -- doesn't work, not owner of relationship");
tx.begin();
List<GroupMember> groups = new ArrayList<>();
groups.add(group);
user.setGroupList(groups);
em.merge(user);            
tx.commit();
em.clear();

// update groups for userId 1 -- works
System.out.println("update groups for userId 1 -- works");
tx.begin();
for ( GroupMember groupMember: groups) {
    groupMember.getGroupMemberList().add(user);
    em.merge(groupMember);            
}
tx.commit();
em.clear();

Gives the following SQL output:

Hibernate: insert into User (id) values (?)
Hibernate: insert into GroupMember (id) values (?)
update users for groupId 2
Hibernate: select groupmembe0_.id as id1_0_0_ from GroupMember groupmembe0_ where groupmembe0_.id=?
Hibernate: select groupmembe0_.groupList_id as groupLis1_1_0_, groupmembe0_.groupMemberList_id as groupMem2_1_0_, user1_.id as id1_4_1_ from GroupMember_User groupmembe0_ inner join User user1_ on groupmembe0_.groupMemberList_id=user1_.id where groupmembe0_.groupList_id=?
Hibernate: select user0_.id as id1_4_0_ from User user0_ where user0_.id=?
Hibernate: insert into GroupMember_User (groupList_id, groupMemberList_id) values (?, ?)
update groups for userId 1 -- doesn't work, not owner of relationship
Hibernate: select user0_.id as id1_4_0_ from User user0_ where user0_.id=?
Hibernate: select groupmembe0_.id as id1_0_0_ from GroupMember groupmembe0_ where groupmembe0_.id=?
update groups for userId 1 -- works
Hibernate: select groupmembe0_.id as id1_0_0_ from GroupMember groupmembe0_ where groupmembe0_.id=?
Hibernate: select groupmembe0_.groupList_id as groupLis1_1_0_, groupmembe0_.groupMemberList_id as groupMem2_1_0_, user1_.id as id1_4_1_ from GroupMember_User groupmembe0_ inner join User user1_ on groupmembe0_.groupMemberList_id=user1_.id where groupmembe0_.groupList_id=?
Hibernate: delete from GroupMember_User where groupList_id=?
Hibernate: insert into GroupMember_User (groupList_id, groupMemberList_id) values (?, ?)
Hibernate: insert into GroupMember_User (groupList_id, groupMemberList_id) values (?, ?)

Reference: MappedBy in bi-directional @ManyToMany : what is the reason

JPA - difference in the use of the mappedBy property to define the owning entity

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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