database 更新父级时休眠@OneToMany 从列表中删除子级

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14686595/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 08:52:10  来源:igfitidea点击:

Hibernate @OneToMany remove child from list when updating parent

databasehibernatejpaassociationsone-to-many

提问by AndaP

I have the following entities:

我有以下实体:

TEAM

团队

@Entity
@Table
public class Team {
[..]
private Set<UserTeamRole> userTeamRoles;

/**
 * @return the userTeamRoles
 */
@OneToMany(cascade = { CascadeType.ALL }, mappedBy = "team", fetch = FetchType.LAZY)
public Set<UserTeamRole> getUserTeamRoles() {
    return userTeamRoles;
}

/**
 * @param userTeamRoles
 *            the userTeamRoles to set
 */
public void setUserTeamRoles(Set<UserTeamRole> userTeamRoles) {
    this.userTeamRoles = userTeamRoles;
}

}

}

and

USER_TEAM_ROLE

USER_TEAM_ROLE

@Entity
@Table(name = "user_team_role")
public class UserTeamRole {

 @ManyToOne(cascade = CascadeType.MERGE, fetch = FetchType.LAZY)
 @JoinColumn(name = "FK_TeamId")
 public Team getTeam() {
    return team;
 }
}

Now, when updating a Team entity that contains for example Team.userTeamRoles = {UTR1, UTR2} with {UTR1, UTR3}, I want UTR2 to be deleted. But the way I do it now, the old list remains the same and it only adds UTR3 to the list.

现在,当更新包含例如 Team.userTeamRoles = {UTR1, UTR2} 和 {UTR1, UTR3} 的团队实体时,我希望删除 UTR2。但我现在这样做的方式是,旧列表保持不变,只将 UTR3 添加到列表中。

This is how I do it at the moment:

这就是我目前的做法:

 if (!usersDualListData.getTarget().isEmpty()) {
        // the role for each user within the team will be "employee"
        team.setUserTeamRoles(new HashSet<UserTeamRole>());
        Role roleForUser = roleService
                .getRoleByName(RoleNames.ROLE_EMPLOYEE.name());
        for (User user : usersDualListData.getTarget()) {
            UserTeamRole utr = new UserTeamRole();
            utr.setUser(user);
            utr.setTeam(team);
            utr.setRole(roleForUser);
            team.getUserTeamRoles().add(utr);
        }
    }

teamService.updateTeam(team);

I thought that by doing team.setUserTeamRoles(new HashSet<UserTeamRole>());the list would be reset and because of the cascades the previous list would be deleted.

我认为这样做team.setUserTeamRoles(new HashSet<UserTeamRole>());会重置列表,并且由于级联,先前的列表将被删除。

Any help is appreciated. Thank you

任何帮助表示赞赏。谢谢

回答by Adam Dyga

  1. Instead of replacing the collection (team.setUserTeamRoles(new HashSet<UserTeamRole>());) you have to clear()the existing one. This happens because if Hibernate loads the entity (and its collections) from DB, it "manages" them, ie. tracks their changes. Generally when using Hibernate it's better notto create any setters for collections (lists, sets). Create only the getter, and clear the collection returned by it, ie:

    team.getUserTeamRoles().clear();

  2. Another thing is that you miss orphan deletion (ie. delete child object when it's removed from collection in the parent). To enable it, you need to add @OneToMany(orphanRemoval=true)in owning entity.

  1. team.setUserTeamRoles(new HashSet<UserTeamRole>());您必须替换现有集合,而不是替换集合 ( ) clear()。发生这种情况是因为如果 Hibernate 从 DB 加载实体(及其集合),它会“管理”它们,即。跟踪他们的变化。通常,在使用 Hibernate 时,最好不要为集合(列表、集合)创建任何 setter。只创建getter,并清除它返回的集合,即:

    team.getUserTeamRoles().clear();

  2. 另一件事是您错过了孤儿删除(即,从父对象的集合中删除子对象时删除子对象)。要启用它,您需要添加@OneToMany(orphanRemoval=true)拥有实体。