4

我正在使用 JPA 2.0、Hibernate 4.1.0.Final、Spring 3.1.1.RELEASE 和 Java 1.6。我有这个实体与另一个实体存在一对多关系……</p>

import javax.persistence.CascadeType;
...
@Entity
@Table(name = "classroom")
public class Classroom implements Serializable
{
    ...

    @OneToMany(mappedBy = "classroom", cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REMOVE})
    private Set<ClassroomUser> roster;

但是,当我使用一组不同的 ClassroomUser 对象更新我的实体时

classroom.setRoster(newRoster);

并保存实体,所有之前的 ClassroomUser 对象都将保留。在从数据库中删除所有孤立记录的同时更新我的​​实体的正确/最短方法是什么?

谢谢, - 戴夫

4

1 回答 1

7

使用orphanRemoval

@OneToMany(mappedBy="classroom", cascade={CascadeType.ALL}, orphanRemoval=true)

每当从持久集中删除条目时,它将被删除。这意味着您需要使用持久集。即不允许您更换套装,而是您应该这样做:

classroom.getRoster().clear();
classroom.getRoster().addAll(newRoster);

示例如何将持久集与用户所需集同步:

/**
 * Assemble ClassroomUser relations.
 * @param classroom Classroom entity. Must be attached persistent or transient. Never null.
 * @param userIds Collection of user identifiers. Can be empty. Never null.
 */
private void assembleClassroomUsers(Classroom classroom, Collection<Integer> userIds) {
    // Make sure relation set exists (might be null for transient instance)
    if (classroom.getUsers() == null) {
        classroom.setUsers(new HashSet<ClassroomUser>());
    }
    // Create working copy of the collection
    Collection<Integer> ids = new HashSet<Integer>(userIds);
    // Check existing relations and retain or remove them as required
    Iterator<ClassroomUser> it = classroom.getUsers().iterator();
    while (it.hasNext()) {
        Integer userId = it.next().getUser().getId();
        if (!ids.remove(userId)) {
            it.remove(); // This will be picked by the deleteOrphans=true
        }
    }
    // Create new relations from the remaining set of identifiers
    for (Integer userId : ids) {
        ClassroomUser classroomUser = new ClassroomUser();
        classroomUser.setClassroom(classroom);
        // User must not have ClassroomUser relations initialized, otherwise Hibernate 
        // will get conflicting instructions what to persist and what to drop => error.
        // It might be safer to use dummy transient instance...
        User dummyUser = new User();
        dummyUser.setId(userId);
        classroomUser.setUser(dummyUser);
        classroom.getUsers().add(classroomUser);
    }
}

这种方法可能看起来有点复杂。您可以使用自定义equals/hashCode和一些Set<E>操作方法(例如来自 Guava)创建更简单的东西(但可能不会太多)。

于 2013-06-10T14:17:28.927 回答