如何在 Hibernate/JPA 中的 mapping/child table 上删除现有记录并插入新记录

How to delete existing records and insert new records on a mapping/child table in Hibernate/JPA

表格

+--------------+-------------+------------+
| USER         |             |            |
| ID           | USERNAME    |            |
| 1            | Jon         |            |
| 2            | Bob         |            |
| PROJECT      |             |            |
| ID           | PROJECTNAME |            |
| 1            | Java        |            |
| 2            | DevOps      |            |
| 3            | DotNet      |            |
| 4            | Testing     |            |
| 5            | Node        |            |
| USER_PROJECT |             |            |
| ID           | USER_ID     | PROJECT_ID |
| 1            | 1           | 1          |
| 2            | 1           | 2          |
| 3            | 1           | 3          |
+--------------+-------------+------------+


 User{
     ...
    @OneToMany(mappedBy="user", cascade=CascadeType.ALL, fetch=FetchType.LAZY, orphanRemoval=true)
        @Getter @Setter private Set<UserProject> userProjects;
    ...
    }

    Project{
        @OneToMany(mappedBy="project", cascade = CascadeType.ALL, fetch = FetchType.EAGER, orphanRemoval=true)
        @Fetch(FetchMode.JOIN)
        @Getter @Setter private Set<UserProject> userProjects;
    }

    UserProject{
        ....
        @ManyToOne
        @JoinColumn(name = "user_id")
        @Getter @Setter private User user;

        @ManyToOne
        @JoinColumn(name = "project_id")
        @Getter @Setter private Project project;

        @ManyToMany(cascade = {CascadeType.ALL}, fetch = FetchType.EAGER)
        @JoinTable(name="user_project_role",
            joinColumns={@JoinColumn(name="user_project_id")},
            inverseJoinColumns={@JoinColumn(name="role_id")})
        @Getter @Setter private Set<Role> roles;

    ...
    }

服务实现方法:

public User updateUserDetails(User user){
        User updatedUser = userDAO.findOne(user.getId());
        for(Iterator<UserProject> iterator = updatedUser.getUserProjects().iterator(); iterator.hasNext();){
            UserProject userProject = iterator.next();
            if(!user.getUserProjects().contains(userProject)){
              //I have even changed the USER_PROJECT.USER_ID constraint to NOT-NULL for this line to work
              userProject.setUser(null);
            }
        }
        return userDAO.save(updatedUser);
    }

我的 UI 为用户提供添加和删除现有项目的选项。

我打算删除并插入 USER_PROJECT。但是我无法为用户删除现有项目。我只能为用户添加新选择的项目。

我在这里做错了什么? 如果不清楚,请评论。

环境 Hiberante 4.x/JPA, Spring 4.x/Spring 数据 JPA

我假设 UserProject 映射是一个有意识的选择,因为角色有额外的数据(如果不是,你通常不会映射 table)。

孤立删除显然无法工作,因为用户和项目都引用了它 table。

所以要删除,您需要找到 UserProject 关联,从用户和项目的两个集合中删除它,从持久性连接中显式删除它,提交事务。

例如:

public User updateUserDetails(User template){
    User toUpdate = EM.find(User.class,template.getId());
    Set<UserProject> present = template.getUserProjects();//the ones should be kept
    Set<UserProject> toDel = new HashSet<>(toUpdate.getUserProjects());
    toDel.removeAll(present); //the difference so the once should be removed
    Set<UserProjcet> newOnes = new HashSet<>(present);
    newOnes.removeAll(toUpdate.getUserProjects()); //freshly added
    for (UserProject uP : toDel) {
        up.getProject().getUserProjects().remove(uP); //from each project removing reference to UserProject
        toUpdate.getUserProjects().remove(uP);
        EM.remove(uP); //removing the actuall 
    }
    toUpdate.getUserProjects().addAll(newOnes);
    return toUpdate;
}

如果您发现要删除的 UserProjects,将用户和项目都设置为 null 并将其删除(您仍然必须在用户项目上调用 Em.remove)而不更新列出。

首先我没明白你在上面的代码中试图删除 UserProject 记录的地方。

如果updateUserDetails是您试图删除UserProject记录的方法,那么它是错误的。能否请您澄清一下。