本文介绍了在JPA或Hibernate中更新ManyToMany关系的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两个Entity,如下所示...

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
}

我想有时使用以下方法来更新User,有时也要更新Group ...

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

方法#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;
}

方法#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;
}

第一种方法可以正常工作,但第二种则不能.但是,当我将join tableGroup.class移到User.class时,第二种方法可以正常工作,而不是第一种.

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.

推荐答案

问题是Owning Entity问题.

假定StaffUser的子类,则您的问题是,关系的仅一方是拥有实体. mappedBy = "groupMemberList"使Group实体成为拥有实体,因此仅保留对该实体的更改.这意味着在两种情况下,您都必须更新Group实体中的groupMemberList.如果您有User的组列表,则必须遍历组列表并将User添加到其中. User中的groupList仅用于检索.

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.

给出UserGroupMember实体:

@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;

然后:

// 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();

给出以下SQL输出:

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 (?, ?)

参考: MappedBy是双向的@ManyToMany:是什么原因

JPA -使用mapledBy属性定义拥有实体的区别

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

这篇关于在JPA或Hibernate中更新ManyToMany关系的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-05 01:18