保存子数据时传递的分离实体持久化

新手上路,请多包涵

提交表单时出现此错误:

org.hibernate.PersistentObjectException:传递给持久化的分离实体: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)
    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>

我究竟做错了什么?

原文由 keysersoze 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 411
2 个回答
teamService.save(team);

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

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 对象已分离(意味着该对象的实例已保存到数据库中但该对象不在会话中).由于您已指定,Hibernate 正在尝试保存它:

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

所以,有几种方法可以修复它:

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

  1. 使用“saveOrUpdate()”方法代替“save()”。 ‘saveOrUpdate()’ 方法接受瞬态和分离的对象。但这种方法的问题在于设计:当你保存团队对象时,你真的需要插入/更新帐户吗?我会把它分成两个操作,并防止从团队更新帐户。

希望这可以帮助。

原文由 Ilya Ovesnov 发布,翻译遵循 CC BY-SA 3.0 许可协议

发生错误是因为设置了 id 。 Hibernate 区分瞬态对象和分离对象,并且持久化仅适用于瞬态对象。

 isteamService.save(team);

在此操作中无法加载 id 因为是 @GeneratedValue

原文由 borchvm 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题