Подтвердить что ты не робот

Hibernate @OneToMany удаляет дочерний элемент из списка при обновлении родительского

У меня есть следующие объекты:

КОМАНДА

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

}

и

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

Теперь, обновляя объект Team, который содержит, например, Team.userTeamRoles = {UTR1, UTR2} с {UTR1, UTR3}, я хочу, чтобы 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);

Я думал, что, выполнив team.setUserTeamRoles(new HashSet<UserTeamRole>());, список будет reset, и из-за каскадов предыдущий список будет удален.

Любая помощь приветствуется. Спасибо вам

4b9b3361

Ответ 1

  • Вместо замены коллекции (team.setUserTeamRoles(new HashSet<UserTeamRole>());) вам нужно clear() существующую. Это происходит потому, что если Hibernate загружает сущность (и ее коллекции) из БД, она "управляет" ими, т.е. отслеживает их изменения. Как правило, при использовании Hibernate лучше не создавать любые сеттеры для коллекций (списки, наборы). Создайте только получателя и очистите возвращаемую им коллекцию, то есть:

    team.getUserTeamRoles().clear();

  • Другое дело, что вы пропускаете удаление сирот (т.е. удаляете дочерний объект при его удалении из коллекции в родительском элементе). Чтобы включить его, вам нужно добавить @OneToMany(orphanRemoval=true) в собственный объект.