2011-09-09 44 views
2

有什麼辦法來強制JPA 2 w/Hibernate中的對象的持久性順序?在JPA 2 w/Hibernate中強制傳遞持久性順序?

假設我有三類:Parent,ChildDeskParent通過@OneToMany擁有ChildDesk的集合;一個Child可以有一個Desk。此外,Parent定義了兩個集合傳遞的持久性,但Child不其Desk定義傳遞持久性:

class Parent { 
    @OneToMany(cascade=CascadeType.ALL) Collection<Child> children; 
    @OneToMany(cascade=CascadeType.ALL) Collection<Desk> desks; 
    ... 
} 

class Child { 
    @OneToOne(cascade={}) Desk desk; 
    @ManyToOne Parent parent; 
} 

class Desk { 
    @ManyToOne Parent parent; 
} 

理想情況下,我想創建在同一時間一張書桌和一個兒童和持續的關係:

Parent parent = em.find(...); 
Child child = new Child(); 
Desk desk = new Desk(); 
// add both desk and child to parent collections here 
// set Parent attribute on both desk and child 

如果我在事務執行上面的代碼,從休眠級聯Parent到其新Child並試圖堅持新Child對象。不幸的是,這會導致「對象引用未保存的瞬態實例」錯誤,因爲從ParentDesk的級聯尚未導致新的對象仍未被保存。

我知道我可以用一個EntityManager的flush()操作(em.flush())解決問題 - 創建Child,創建Desk,重視既Parentem.flush(),然後連接到DeskChild,但我不超 - 用em.flush()來拋棄我的代碼來保存新的持久對象的複雜圖形。是否有不同的方式向JPA 2或Hibernate發信號通知應該始終堅持新的Desk而不是新的Child

+0

爲什麼您的「OneToOne」級聯類型爲空?它不應該至少是「PERSIST」嗎?而且,你如何知道從Paren到Child的Hibernate級聯?可能Desk失敗,因爲它試圖從父級級聯失敗,而不是從Child級聯。 – edutesoy

+0

Desk對象的生命週期由Parent對象的生命週期而不是Child對象決定,因此Parent.desks具有CascadeType.ALL而Child.desk沒有級聯。 我有單元測試確認級聯從'Parent'到'Desk'對象的集合,從'Parent'到它的'Child'對象的集合。 – BobG

回答

1

看你的描述,我認爲持續性系統會先嚐試堅持按以下順序:

  • 首先Parent.children [I]
  • 每個兒童[I]有一個短暫的指針臺。系統無法保留它,因爲您尚未將其配置爲Cascade.Persist。

然後,當持續Desk,並且您認爲它在路徑Parent.desks [i](它被配置爲Cascade)時失敗,但可能失敗不是來自此路徑。

+0

將CascadeType.PERSIST添加到Child.desk * *會實現所需的行爲。我不一定非常喜歡這個選項,但它比用em.flush()亂丟我的代碼更好。 – BobG