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

Java 如何在Hibernate/JPA中删除现有记录并在映射/子表上插入新记录,java,spring,hibernate,jpa,Java,Spring,Hibernate,Jpa,表格 +--------------+-------------+------------+ | USER | | | | ID | USERNAME | | | 1 | Jon | | | 2 | Bob | | | PROJECT |

表格

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

    ...
    }
用户{
...
@OneToMany(mappedBy=“user”,cascade=CascadeType.ALL,fetch=FetchType.LAZY,orphan=true)
@Getter@Setter私有集合用户项目;
...
}
计划{
@OneToMany(mappedBy=“project”,cascade=CascadeType.ALL,fetch=FetchType.EAGER,orphan=true)
@Fetch(FetchMode.JOIN)
@Getter@Setter私有集合用户项目;
}
用户项目{
....
@许多酮
@JoinColumn(name=“user\u id”)
@Getter@Setter私有用户;
@许多酮
@JoinColumn(name=“project\u id”)
@Getter@Setter私人项目;
@ManyToMany(cascade={CascadeType.ALL},fetch=FetchType.EAGER)
@JoinTable(name=“user\u project\u role”,
joinColumns={@JoinColumn(name=“user\u project\u id”)},
inverseJoinColumns={@JoinColumn(name=“role\u id”)})
@Getter@Setter私有集角色;
...
}
服务实现方法:

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);
    }
public User updateUserDetails(用户用户){
User updateuser=userDAO.findOne(User.getId());
for(Iterator Iterator=UpdateUser.getUserProjects().Iterator();Iterator.hasNext();){
UserProject=iterator.next();
如果(!user.getUserProjects()包含(userProject)){
//我甚至将USER\u PROJECT.USER\u ID约束更改为NOT-NULL,以使此行正常工作
userProject.setUser(null);
}
}
返回userDAO.save(updateUser);
}
“我的UI”为用户提供了添加和删除现有项目的选项

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

我做错了什么? 如果不清楚,请发表评论

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

我假设用户项目映射是一种消费选择,因为角色有其他数据(如果没有,通常不映射该表)

孤儿删除显然无法工作,因为它同时被用户和项目表引用

所以要删除,您需要找到UserProject关联,从user和project的两个集合中删除它,从persistant contect,commit事务中显式删除它

例如:

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;
}
public User updateUserDetails(用户模板){
User toUpdate=EM.find(User.class,template.getId());
Set present=template.getUserProjects();//应该保留这些项目
Set toDel=newhashset(toUpdate.getUserProjects());
toDel.removeAll(present);//差异,因此应删除once
Set newOnes=新哈希集(存在);
newOnes.removeAll(toUpdate.getUserProjects());//新添加
for(UserProject-uP:toDel){
up.getProject().getUserProjects().remove(up);//从每个项目删除对UserProject的引用
toUpdate.getUserProjects().remove(向上);
EM.remove(uP);//删除实际
}
toUpdate.getUserProjects().addAll(新项目);
返回更新;
}

如果您找到要删除的UserProjects,将user和project都设置为null并在不更新列表的情况下删除它(您仍然需要在user-project上调用Em.remove),那么它也可能会起作用(目前还不确定)。

首先,在上面的代码中,我没有找到您试图删除UserProject记录的地方

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