如何在 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记录的方法,那么它是错误的。能否请您澄清一下。
表格
+--------------+-------------+------------+
| 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记录的方法,那么它是错误的。能否请您澄清一下。