保存子数据时传递的分离实体可持久保存 [英] Detached entity passed to persist when save the child data

查看:90
本文介绍了保存子数据时传递的分离实体可持久保存的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

提交表单时出现此错误:

I'm getting this error when submitting the form:

org.hibernate.PersistentObjectException:分离的实体传递给持久化:com.project.pmet.model.Account;嵌套异常是javax.persistence.PersistenceException:org.hibernate.PersistentObjectException:传递给持久对象的分离实体:com.project.pmet.model.Account

org.hibernate.PersistentObjectException: detached entity passed to persist: com.project.pmet.model.Account; nested exception is javax.persistence.PersistenceException: org.hibernate.PersistentObjectException: detached entity passed to persist: com.project.pmet.model.Account

这是我的实体:

帐户:

@Entity
@DynamicInsert
@DynamicUpdate
public class Account {

    @Id
    @GeneratedValue
    private Integer id;

    @Column(nullable = false)
    private String login;

    @Column(nullable = false)
    private String password;

    @Column(nullable = false)
    private String email;

    @ManyToOne
    @JoinColumn(name = "team_id")
    private Team team;

    @OneToMany(cascade = CascadeType.ALL, mappedBy = "owner")
    private List<Team> ownedTeams;

    ...

团队:

@Entity
@DynamicInsert
@DynamicUpdate
public class Team {

    @Id
    @GeneratedValue
    private Integer id;

    @Column(nullable = false)
    private String name;

    @ManyToOne
    @JoinColumn(name = "owner_id", nullable = false)
    private Account owner;

    @OneToMany(cascade = CascadeType.ALL, mappedBy = "team")
    private List<Account> members;

    ...

这是控制器的一部分:

    @ModelAttribute("team")
    public Team createTeamObject() {
        return new Team();
    }

    @RequestMapping(value = "/teams/create-team", method = RequestMethod.GET)
    public String getCreateTeam(@ModelAttribute("team") Team team, Principal principal) {
        logger.info("Welcome to the create team page!");

        Account owner = accountService.findOneByLogin(principal.getName());
        team.setOwner(owner);
        team.setMembers(new AutoPopulatingList<Account>(Account.class));

        return "teams";
    }

    @RequestMapping(value = "/teams/create-team", method = RequestMethod.POST)
    public String postCreateTeam(@ModelAttribute("team") Team team) {
        logger.info("Team created!");

        teamService.save(team);

        return "redirect:/teams.html";
    }

和表格:

<form:form commandName="team" id="teamForm">
      <div class="form-group">
          <label>Name</label>
          <form:input path="name" cssClass="form-control" />
      </div>
      <div class="form-group" id="row-template">
          <label>Members</label>
          <form:select path="members[0].id" cssClass="form-control" data-live-search="true" >
             <form:options items="${accounts}" itemValue="id" />
          </form:select>
          ...
      </div>
   <form:hidden path="owner.id" />
</form:form>

我在做什么错了?

推荐答案

teamService.save(team);

Save方法仅接受瞬态对象.您可以在此处找到临时对象是什么?

Save method accepts only transient objects. What is the transient object you can find here

Transient - an object is transient if it has just been instantiated using the new operator, and it is not associated with a Hibernate Session. It has no persistent representation in the database and no identifier value has been assigned. Transient instances will be destroyed by the garbage collector if the application does not hold a reference anymore. Use the Hibernate Session to make an object persistent (and let Hibernate take care of the SQL statements that need to be executed for this transition).

您正在获取Team对象,并尝试将其持久化到数据库中,但是该对象中包含Account对象,并且该Account对象已分离(意味着该对象的实例已保存到DB中,但该对象未保存)在会话中). Hibernate正在尝试保存它,因为您已指定:

You are getting the Team object and you are trying to persist it to the DB but that object has Account object in it and that Account object is detached (means that instance of that object has saved into the DB but that object is not in the session). Hibernate is trying to save it because of you have specified:

@OneToMany(cascade = CascadeType.ALL, ....

因此,有几种解决方法:

So, there are few ways how you can fix it:

1)不要使用CascadeType.ALL配置.帐户对象可用于团队数量(至少域结构允许),并且更新操作可能会更新所有团队的帐户-这意味着此操作不应随团队更新而启动. 如果确实需要使用MERGE/DELETE配置,我将从那里删除级联参数(默认值是不执行级联操作).但是,如果您确实需要坚持下去,请参阅选项#2

1) do not use CascadeType.ALL configuration. Account object can be used for number of Teams (at least domain structure allows it) and update operation might update Account for ALL Teams -- it means that this operation should not be initiated with Team update. I would remove cascade parameter from there (default value is no cascade operations), of if you really need use MERGE/DELETE configuration. But if you really need to persist it then see option #2

2)使用"saveOrUpdate()"方法代替"save()". "saveOrUpdate()"方法接受瞬态和分离的对象. 但是这种方法的问题在于设计:在保存团队对象时,您真的需要插入/更新帐户吗?我将其分为两个操作,并阻止从团队更新Account.

2) use 'saveOrUpdate()' method instead of 'save()'. 'saveOrUpdate()' method accepts transient and detached objects. But the problem with this approach is in design: do you really need to insert/update account when you are saving Team object? I would split it in two operations and prevent updating Account from the Team.

希望这会有所帮助.

这篇关于保存子数据时传递的分离实体可持久保存的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆