【问题标题】:Many to many with custom entity in hibernate - cascade not working properly多对多与休眠中的自定义实体 - 级联无法正常工作
【发布时间】:2012-05-26 19:22:06
【问题描述】:

在我的项目中,我需要 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);
    }
}

InspectorAssignment

@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 中的等于和哈希码方法(我的所有实体都扩展的类)

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

【问题讨论】:

  • 也许你需要一些身份属性...
  • 我忘了说我有这些,它们在我正在扩展的 AbstractPersistentObject 中。

标签: java hibernate many-to-many


【解决方案1】:

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

我愿意

  • 在分配表中对 userId-projectId 创建唯一约束,以确保不会发生这种情况并改为引发异常
  • 仅在尚不存在的情况下创建新的 InspectorAssignment
  • 通过显式保存在数据库中创建 InspectorAssignment,而不是依靠从 Project 到 InspectorAssignment 的级联
  • 在 InspectorAssignment 中覆盖 equals()hashCode()

【讨论】:

  • 我更新了我的帖子并添加了我的 equals 和 hashcode 方法。我将自己坚持 InspectorAssignment 以便它获得一个 id 并且 equals 将返回 true。谢谢:)
  • Hibernate 建议不要使用自动生成的 ID 来实现 equals 和 hashCode(尽管通常很难做到)。但请注意,如果您的实体没有 ID,而您将其添加到 Set 中,则会出现问题。
  • 如果有人愿意看一下我的问题,我会很高兴,因为我无法进行多对多的更新工作。谢谢。 stackoverflow.com/questions/24737145/…
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-02-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多