复合键与实体

时间:2016-02-03 14:40:38

标签: java spring hibernate spring-mvc spring-data-jpa

我收到错误

  

org.springframework.dao.InvalidDataAccessApiUsageException:已分离   实体传递给持久化:com.websopti.wotms.entity.Project;嵌套   异常是org.hibernate.PersistentObjectException:分离的实体   传递给持久化:com.websopti.wotms.entity.Project

我在实体上有复合键加入基本上我有两个实体一个是项目,一个是用户我通过调用另一个实体创建了它们之间的复合键连接 ProjectUser 以下是类

用户

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
}

项目

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
}

现在当我创建项目时,如果我设置列表对象并保存然后它工作正常,但当我想更新该项目并设置由代码和集手动创建的修改列表对象项目对象。所以现在当我尝试保存这个修改过的项目对象时,我得到的错误是&#34;传递给分离的实体持续存在&#34;。

我喜欢关注并保存此项目对象 我的代码用于保存项目对象控制器方法,如下面的

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

    }

请帮助我,我被困在这里

1 个答案:

答案 0 :(得分:0)

首先感谢 hansnae 让我有信心处理这个问题,因为我已经访问过这个问题3次并且经过那个问题也认为应用该解决方案但是因为我没有应用我不确定。

现在我的情况下出现了双向关系问题,所以我已经在List对象中应用了这个逻辑进行修改,它对我起作用了

JPA/Hibernate: detached entity passed to persist

但在那个问题中删除对象工具对我不起作用,因为我在我的情况下使用了复合键连接我需要额外工作来删除该对象

当我尝试保存已删除的对象并在相关的连接实体中设置null时,我的情况会抛出异常

  

复合标识符的任何部分都不能为空

所以要从列表中删除该对象,我必须通过存储库删除查询手动删除该对象。

感谢您帮助并提升了这个伟大的社区