分离的实体传递给持久性错误 [英] Detached entity passed to persist error

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

问题描述

在提交表单时出现此错误:



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



这是我的实体:



帐户:

  @Entity 
@DynamicInsert
@DynamicUpdate
public class Account {

@Id
@GeneratedValue
private Integer id;

@Column(nullable = false)
私有字符串登录;

@Column(nullable = false)
私人字符串密码;

@Column(nullable = false)
private String email;

@ManyToOne
@JoinColumn(name =team_id)
私人团队;

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


团队:

  @Entity 
@DynamicInsert
@DynamicUpdate
public class Team {

@Id
@GeneratedValue
私人整数ID;

@Column(nullable = false)
私有字符串名称;

@ManyToOne
@JoinColumn(name =owner_id,nullable = false)
私人账户拥有者;

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

...

以下是控制器的一部分:

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

@RequestMapping(value =/ teams / create-team,method = RequestMethod.GET)
public String getCreateTeam(@ModelAttribute(team)Team team ,校长){
logger.info(欢迎来到创建团队页面!);

帐户所有者= accountService.findOneByLogin(principal.getName());
team.setOwner(owner);
team.setMembers(new AutoPopulatingList< Account>(Account.class));

返回团队;
}

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

teamService.save(team);

返回redirect:/teams.html;
}

形式如下:

 < form:form commandName =teamid =teamForm> 
< div class =form-group>
< label>名称< / label>
< form:input path =namecssClass =form-control/>
< / div>
< div class =form-groupid =row-template>
< label>会员< / label>
< form:select path =members [0] .idcssClass =form-controldata-live-search =true>
< form:options items =$ {accounts}itemValue =id/>
< / form:select>
...
< / div>
< form:hidden path =owner.id/>
< / form:form>

我做错了什么?

解决方案

  teamService.save(team); 

Save方法只接受瞬态对象。您可以在此处找到什么是瞬态对象

Transient - 如果一个对象刚刚使用new运算符实例化,并且与Hibernate Session没有关联,则该对象是暂时的。它在数据库中没有持久表示并且没有分配标识符值。如果应用程序不再拥有引用,则垃圾收集器将销毁瞬态实例。使用Hibernate Session使对象持久化(并让Hibernate处理需要为此转换执行的SQL语句)。



您正在获取Team对象,并且您试图将其持久保存到数据库中,但该对象中包含Account对象,并且Account对象被分离(意味着该对象的实例已保存到数据库中,但该对象不在会话)。 Hibernate试图保存它,因为你已经指定了:

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

因此,您可以通过几种方式解决问题:

<1>不使用CascadeType.ALL配置。账户对象可用于团队数量(至少域结构允许),更新操作可能会更新所有团队的账户 - 这意味着此操作不应以团队更新启动。
如果您真的需要使用MERGE / DELETE配置,我会从那里删除级联参数(默认值不是级联操作)。但是,如果你真的需要坚持下去,那么看看选项#2



<2>使用'saveOrUpdate()'方法而不是'save()'。 'saveOrUpdate()'方法接受瞬态和分离对象。
但是这种方法的问题在于设计:当您保存Team对象时,是否真的需要插入/更新帐户?我将它分成两个操作,并阻止更新帐户从团队。



希望这可以帮助。


I'm getting this error when submitting the form:

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

Here are my entities:

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;

    ...

Team:

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

    ...

Here's a part of the Controller:

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

And the form:

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

What am I doing wrong?

解决方案

teamService.save(team);

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).

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) 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) 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.

Hope this helps.

这篇关于分离的实体传递给持久性错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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