表格
+--------------+-------------+------------+
| 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 |
+--------------+-------------+------------+
类(class)
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 Data JPA
最佳答案
我认为 UserProject 映射是一个明智的选择,因为角色有附加数据(如果不是,您通常不会映射该表)。
孤立删除显然无法工作,因为它被用户和项目表引用。
因此,要删除,您需要找到 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)而不更新列表,它也可能有效(尚不确定)。
关于java - 如何在 Hibernate/JPA 中的映射/子表上删除现有记录并插入新记录,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28616935/