2014-12-27 57 views
9

提交表單時,我得到這個錯誤:獨立實體傳遞堅持錯誤

org.hibernate.PersistentObjectException:通過堅持脫離實體:com.project.pmet.model.Account;嵌套的例外是javax.persistence.PersistenceException:org.hibernate.PersistentObjectException:通過堅持脫離實體: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> 

我在做什麼錯?

回答

20
teamService.save(team); 

保存方法只接受瞬態對象。什麼是短暫的對象,你可以找到

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

你所得到的團隊目標和你想它堅持到數據庫,但該對象是否具有客戶對象在它和客戶對象是分離(手段該對象的實例已保存到數據庫中,但該對象不在會話中)。 Hibernate是試圖挽救它,因爲你已經指定:

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

因此,有幾個方法,你可以如何解決:

1)不使用CascadeType.ALL配置。賬戶對象可用於團隊數量(至少域結構允許),更新操作可能會更新所有團隊的賬戶 - 這意味着此操作不應以團隊更新啓動。 如果您真的需要使用MERGE/DELETE配置,我會從那裏刪除級聯參數(默認值不是級聯操作)。但是如果你真的需要堅持下去,那麼看到選項#2

2)使用'saveOrUpdate()'方法而不是'save()'。 'saveOrUpdate()'方法接受瞬態和分離對象。 但是這種方法的問題在於設計:在保存Team對象時,是否真的需要插入/更新帳戶?我會將其拆分爲兩個操作,並阻止從團隊更新帳戶。

希望這會有所幫助。

+0

爲第一個解決方案投票,這對我有幫助。 – vtomic85

10

發生錯誤的原因是設置了id。 Hibernate區分瞬態對象和分離對象,並且僅使用瞬態對象持久工作。

isteamService.save(team); 

在此操作無法加載ID,因爲是@GeneratedValue

+1

這就是完美的答案,確保id沒有價值。 –

+1

噢,如果這個id已經被設置,那麼具有'@ GeneratedValue'的id的對象甚至不能保存。我認爲註釋只是某種後備。很高興知道這不是! – Froxx

+1

如果您的數據類型爲「Integer」,並且id數據類型爲「int」,那麼請確保您的ID未設置爲0。 – Ram

0

由於您的ID是自動生成的值,不從客戶端發送。我有同樣的問題。確保您沒有爲自動生成的屬性提供值。