简体   繁体   English

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

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

Tables

+--------------+-------------+------------+
| 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          |
+--------------+-------------+------------+

Classes


 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;

    ...
    }

Service Implementation method: 服务实现方法:

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

My UI provides options to ADD and also REMOVE existing projects for user. 我的UI为用户提供了添加和删除现有项目的选项。

I intend to delete and insert into USER_PROJECT. 我打算删除并插入USER_PROJECT。 However I am unable to REMOVE existing projects for user. 但是,我无法为用户删除现有项目。 Iam only able to ADD newly selected projects for User. Iam仅能为User添加新选择的项目。

What am I doing wrong here? 我在这里做错了什么? Please comment if this is unclear. 如果不清楚,请发表评论。

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

I assume that the UserProject mapping is a consciuse choice because of the roles additional data (if not you normally do not map that table). 我假设UserProject映射是一个明智的选择,因为角色会附加数据(如果没有,通常不映射该表)。

The orphan removal obviously cannot work as it is referenced by both User and Project table. 由于用户表和项目表都引用了孤立删除,因此显然无法正常工作。

So to remove, you need to find the UserProject association, remove it from both sets on user and project, remove it explicit from the persistant contect, commit transaction. 因此,要删除它,您需要找到UserProject关联,将其从用户和项目的两个集合中删除,将其从持久性连接中显式删除,然后提交事务。

For example something like that: 例如这样的事情:

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

It may also work (not sure yet) if you find the UserProjects to delete, set both user and project to null and remove it (you have to still call Em.remove on user project) without updating the lists. 如果您找到要删除的UserProjects,将user和project都设置为null并删除它(您仍然必须在用户项目上调用Em.remove)而不更新列表,则它也可能起作用(尚不确定)。

First thing I didn't get where you are trying to delete the UserProject record in above code. 首先,我没有找到您要删除上述代码中的UserProject记录的位置。

If updateUserDetails is the method where you are trying to delete the UserProject record, Then its wrong. 如果updateUserDetails是您尝试删除UserProject记录的方法,则错误。 Could you please clarify the things. 你能把事情弄清楚吗?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM