2

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

Jens Schauder
  • 77,657
  • 34
  • 181
  • 348
Nick Gajera
  • 81
  • 1
  • 12
  • How many tables do you have here? Based on the entities, I can see you must be having User and Project table. Do you have any other table that stores user-project relationship. Also can you post these table structure? – Madhusudana Reddy Sunnapu Feb 03 '16 at 15:23
  • http://stackoverflow.com/questions/13370221/jpa-hibernate-detached-entity-passed-to-persist – hasnae Feb 03 '16 at 16:01
  • yes i have posted all structure above there is another entity called ProjectUser that store relationship with composite key – Nick Gajera Feb 04 '16 at 05:48

1 Answers1

0

first of all thanks hansnae for giving me confidence to work on that question because i have visited that question 3 times and go through that question also have thinked to apply that solution but not applied because of i'm not sure about that.

now that bidirectional relation ship issue is there in my case so i have applied that logic for modification in List object and it worked for me

JPA/Hibernate: detached entity passed to persist

but in that question remove object facility not worked for me because i have used composite key join in my case i haev to work extra to remove that object

when i try to save removed object and set null in related joined entity then my case it throws Exception

No part of a composite identifier may be null

so to remove that object from list i have to manually remove that object by repository delete query.

Thanks for help and hands up too this great community

Community
  • 1
  • 1
Nick Gajera
  • 81
  • 1
  • 12