如何删除现有记录并在Hibernate / JPA中的映射/子表上插入新记录

时间:2015-02-19 21:08:50

标签: java spring 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);
    }

我的用户界面为ADD提供了选项,并为用户提供了现有项目。

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

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

环境 Hiberante 4.x / JPA,Spring 4.x / Spring Data JPA

2 个答案:

答案 0 :(得分:1)

我认为UserProject映射是一个很好的选择,因为角色附加数据(如果不是你通常不映射该表)。

孤立删除显然无法正常工作,因为User和Project表都引用了它。

所以要删除,你需要找到UserProject关联,从用户和项目的两个集合中删除它,从持久性的contect,commit transaction中删除它。

例如类似的东西:

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,将user和项目设置为null并将其删除(您必须仍然在用户项目上调用Em.remove)而不更新列表,它也可能(还不确定)。

答案 1 :(得分:0)

首先,我没有到达您尝试删除上述代码中的UserProject记录的位置。

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