1

在我的项目中,我需要 2 个具有双向多对多关系的实体。但是,连接表必须与其他表有自己的额外关系,所以我自己为连接表创建了一个新实体。

它应该如下所示:

项目 -- InspectorAssignment -- 用户

将检查员分配添加到项目并将其持久化时,该分配也应该被持久化,并且用户也应该添加该分配。

为此,我在服务中有一个方法:

projectService.assignInspectorToProject(inspector, project);

但是,当我两次运行此方法时,我的表中会创建两条记录。这不应该发生,因为所有的集合都是集合。

有人可以指出我做错了什么吗?

所有相关的方法/类:

项目服务

public void assignInspectorToProject(User user, Project project) {

    if (!user.hasRole("inspector")) {
        throw new RuntimeException("This user is no inspector");
    }

    project.addInspector(user);
    projectDao.save(project);
}

项目

@Entity
public class Project extends AbstractPersistentObject {

    @OneToMany(cascade = {CascadeType.ALL}, mappedBy = "project")
    private Set<InspectorAssignment> inspectorAssignments;  

    public void addInspector(User user) {

        InspectorAssignment assignment = new InspectorAssignment(user, this);
        user.addInspectorAssignment(assignment);

        inspectorAssignments.add(assignment);
    }
}

检查员分配

@Entity
public class InspectorAssignment extends AbstractPersistentObject {

    @ManyToOne
    @NotNull
    private User user;

    @ManyToOne
    @NotNull
    private Project project;

    public InspectorAssignment() {
    }

    public InspectorAssignment(User user, Project project) {
        setUser(user);
        setProject(project);
    }
}

用户

@Entity
public class User extends AbstractPersistentObject implements UserDetails {

     @OneToMany(mappedBy = "user", cascade = {CascadeType.ALL})
     private Set<InspectorAssignment> inspectorAssignments;

     public void addInspectorAssignment(InspectorAssignment assignment) {
         inspectorAssignments.add(assignment);
     }
}
}

AbstractPersistenObject 中的 equals 和 hashcode 方法(我的所有实体都扩展的类)

 @Override
public boolean equals(Object obj) {
    if (this == obj)
        return true;
    if (obj == null)
        return false;
    if (getClass() != obj.getClass())
        return false;
    AbstractPersistentObject other = (AbstractPersistentObject) obj;
    if (id == null) {
        if (other.id != null)
            return false;
    } else if (id.equals(other.id))
        return true;
    return false;
}

@Override
public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + ((id == null) ? 0 : id.hashCode());
    return result;
}
4

1 回答 1

2

这对我来说似乎很合乎逻辑。您调用此方法两次。因此,您创建了两个不同的 InspectorAssignment 实例并同时保存它们。即使您通过保存项目来保存它们,该项目也有一组分配,其中包含两个不同的 InspectorAssignment 实例。Set 不会添加第二个它等于第一个,但它不是,因为你没有覆盖hashCode()and equals()

我会

  • 在分配表中创建唯一约束userId-projectId以确保不会发生这种情况并引发异常
  • 仅在尚不存在时才创建新的 InspectorAssignment
  • 通过显式保存在数据库中创建 InspectorAssignment,而不是依靠从 Project 到 InspectorAssignment 的级联
  • 覆盖equals()hashCode()在 InspectorAssignment
于 2012-05-19T15:05:37.913 回答