i'm getting error like
org.springframework.dao.InvalidDataAccessApiUsageException: detached entity passed to persist: com.websopti.wotms.entity.Project; nested exception is org.hibernate.PersistentObjectException: detached entity passed to persist: com.websopti.wotms.entity.Project
i have Composite key join on entity basically i have two entity one is Project and one is User and i have created composite key join between them by making another Entity called ProjectUser following are classes
User
public class User extends BaseEntity<Long> implements UserDetails {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue
private Long id;
...
@OneToMany(mappedBy="user",fetch=FetchType.LAZY)
private List<ProjectUser> userProjects;
...
getter and setters
}
Project
public class Project extends BaseEntity<Long> {
private static final long serialVersionUID = 7541005803335530236L;
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
...
@OneToMany(mappedBy="project",fetch=FetchType.LAZY, cascade=CascadeType.ALL)
private List<ProjectUser> projectUsers;
...
}
ProjectUser
@IdClass(CompositeKey.class)
public class ProjectUser extends BaseEntity<Long> {
private static final long serialVersionUID = 476483195548055916L;
@ManyToOne
@Id
@JoinColumn(name="user_id", referencedColumnName="id")
private User user;
@ManyToOne
@Id
@JoinColumn(name="project_id", referencedColumnName="id")
private Project project;
private ProjectRole role;
...
getter setter
}
CompositeKey
public class CompositeKey implements Serializable {
private static final long serialVersionUID = 2186028617883601307L;
private long user;
private long project;
public CompositeKey() {}
public CompositeKey(long user, long project) {
this.user = user;
this.project = project;
}
public boolean equals(Object object) {
if (object instanceof CompositeKey) {
CompositeKey pk = (CompositeKey)object;
return user == pk.user && project == pk.project;
} else {
return false;
}
}
...
getter setter
}
now when i create project at that time if i set List object and save then it works fine but when i wanted to update that project and set Modified List object that is manually created by code and set to project object. so now when i try to save this modified project object then i get error for "detached entity passed to persist".
i'm doing like following and saving this project object my code for saving project object controller method like follow
@RequestMapping(value="/update", method=RequestMethod.POST)
public String updateProject(@ModelAttribute("project") Project project, HttpServletRequest request, RedirectAttributes redirectAttributes){
try {
project.setIpAddress(CommonUtils.getClientIpAddr(request));
Project oldProject = projectService.findById(project.getId());
List<ProjectUser> newProjectUsers = new ArrayList<ProjectUser>();
List<Integer> selectedIndexes = project.getSelectedRoleIndexes();
List<User> users = project.getTeam();
if(users != null && users.size() > 0){
for (User u : users) {
newProjectUsers.add(new ProjectUser(u, project, ProjectRole.getRole(selectedIndexes.get(users.indexOf(u)))));
}
}
List<ProjectUser> oldProjectUsers = oldProject.getProjectUsers();
for (ProjectUser projectUser : new ArrayList<>(oldProjectUsers)) {
if(!users.contains(projectUser.getUser())){
/*disable all task for user*/
//taskService.disableUserTaskForProject(projectUser.getUser(), oldProject);
/*send remove member form project mail*/
//projectEmailService.sendProjectTeamMemberRemoveEmail(projectUser.getUser(), oldProject);
oldProjectUsers.remove(projectUser);
}else{
ProjectUser pu = newProjectUsers.get(users.indexOf(projectUser.getUser()));
oldProjectUsers.remove(projectUser);
projectUser.setRole(pu.getRole());
oldProjectUsers.add(projectUser);
}
}
List<User> oldTeam = oldProjectUsers.stream().map(pu -> {return pu.getUser();}).collect(Collectors.toList());
for (ProjectUser projectUser : newProjectUsers) {
if(!oldTeam.contains(projectUser.getUser())){
/*send user add in project mail*/
//projectEmailService.sendProjectTeamMemberAddEmail(projectUser.getUser(), oldProject);
oldProjectUsers.add(projectUser);
}
}
//oldProjectUsers = entityManager.merge(oldProjectUsers);
//projectUserService.updateAllProjectUsers(oldProjectUsers);
/*for (ProjectUser projectUser : oldProjectUsers) {
entityManager.merge(projectUser);
}*/
project.setProjectUsers(oldProjectUsers);
//project = entityManager.merge(project);
project = projectService.update(project);
/*old team except admin*/
/*List<User> oldTeam = oldProject.getProjectUsers()
.stream()
.map(pu -> {return pu.getUser();})
.collect(Collectors.toList());
List<User> newTeam = project.getTeam()
.stream()
.filter(u -> u.getRole() != SystemRole.ADMIN)
.collect(Collectors.toList());
project = projectService.update(project);
for (User user : oldTeam) {
if(!newTeam.contains(user)){
disable all task for user
taskService.disableUserTaskForProject(user, project);
send remove member form project mail
projectEmailService.sendProjectTeamMemberRemoveEmail(user, project);
}
}
for (User user : newTeam) {
if(!oldTeam.contains(user)){
send user add in project mail
projectEmailService.sendProjectTeamMemberAddEmail(user, project);
}
}*/
} catch(Exception e) {
e.printStackTrace();
return "redirect:/user/UserDashboard";
}
redirectAttributes.addFlashAttribute("projectId",project.getId());
redirectAttributes.addFlashAttribute("fromUpdate", true);
return "redirect:/user/"+PageTemplate.userDashboard;
}
please help me i'm stuck here