Reputation: 867
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.
Upvotes: 2
Views: 17851
Reputation: 11561
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
Upvotes: 7