【问题标题】:detached entity passed to persist when Composite key used with entity当复合键与实体一起使用时,分离的实体传递给持久化
【发布时间】:2016-05-12 19:46:33
【问题描述】:

我遇到了类似的错误

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

我在实体上有复合键连接,基本上我有两个实体,一个是 Project,一个是 User,我通过创建另一个名为的实体在它们之间创建了复合键连接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;
    ...
}

项目用户

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

复合键

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
}

现在,当我当时创建项目时,如果我设置 List 对象并保存,那么它工作正常,但是当我想更新该项目并设置由代码手动创建并设置的修改列表对象时到项目对象。所以现在当我尝试保存这个修改后的项目对象时,我收到“传递给持久化的分离实体”的错误。

我正在关注并保存这个项目对象 我用于保存项目对象控制器方法的代码,如下所示

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

    }

请帮帮我,我被困在这里

【问题讨论】:

  • 你这里有几张桌子?根据实体,我可以看到您必须拥有 User 和 Project 表。您是否还有其他存储用户-项目关系的表。你也可以发布这些表结构吗?
  • 是的,我已经发布了上面的所有结构,还有另一个名为 ProjectUser 的实体存储与复合键的关系

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


【解决方案1】:

首先感谢 hansnae 让我有信心解决这个问题,因为我已经访问了该问题 3 次,并且通过该问题也考虑过应用该解决方案,但由于我没有应用我不确定。

现在在我的情况下存在双向关系问题,所以我已将该逻辑应用于 List 对象中的修改,它对我有用

JPA/Hibernate: detached entity passed to persist

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

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

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

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

感谢您的帮助,也感谢这个伟大的社区

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-05-25
    • 2013-06-26
    • 1970-01-01
    • 1970-01-01
    • 2017-04-01
    • 2018-09-22
    • 1970-01-01
    • 2017-10-21
    相关资源
    最近更新 更多