更新父级时,Hibernate @OneToMany会从列表中删除子级

And*_*daP 32 database hibernate jpa associations one-to-many

我有以下实体:

球队

@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;
}
Run Code Online (Sandbox Code Playgroud)

}

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;
 }
}
Run Code Online (Sandbox Code Playgroud)

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

这就是我现在这样做的方式:

 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);
Run Code Online (Sandbox Code Playgroud)

我认为通过执行team.setUserTeamRoles(new HashSet<UserTeamRole>());列表将被重置,并且由于级联,之前的列表将被删除.

任何帮助表示赞赏.谢谢

Ada*_*yga 94

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

    team.getUserTeamRoles().clear();

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

  • 是的,clear + orphanRemoval就是这个伎俩.非常感谢! (2认同)