2011-03-09 30 views
6

這是導致問題的順序:在數據庫JPA:什麼是與惰性初始化集合合併的行爲?

  1. 我有一個球隊戰績和3球員紀錄。隊列實體有一個使用FetchType.LAZY的列表,CascadeType.ALL
  2. 單擊webui上的搜索按鈕
  3. 調用服務器端使用JPA查詢的查詢,查找所有Team記錄,在這種情況下,查詢返回的團隊實體只有1條記錄(其中包含玩家實體列表的代理)
  4. 將此實體映射到DTO,並將此DTO返回到webui,跳過玩家實體列表的映射
  5. Webui呈現HTML格式的DTO,隨時可以接收用戶的修改
  6. 用戶修改團隊的屬性,比如它的時間爲f ounded
  7. 上的WebUI保存按鈕被點擊
  8. 轉換的DTO球隊實體,將被用於更新現有的球隊戰績
  9. 但在這種情況下,如果我是使用em.merge (teamEntity),球隊記錄將會更新,但球員名單會發生什麼?因爲從DTO轉換到團隊實體時,teamEntity有一個空的玩家實體列表。合併後,我注意到teamEntity的細節大小爲0。但刷新該實體後,em.refresh(teamEntity)將返回3的詳細大小。

林困惑於:

  1. 爲什麼是0合併後的尺寸?這就像不再代表記錄
  2. 在做測試之前,我一直在想,因爲我將一個teamEntity與一個空的細節合併在一起,所以細節將被刪除。

請賜教:)

謝謝!

回答

9

JPA規格說:

的語義合併操作 應用到實體X如下:

  • 如果X是一個分離的實體,所述狀態 的X被複制到相同的 身份的預先存在的管理實體實例X'或X的新託管副本X'已創建。

  • 如果X是一個新的實體 例如,一個新的管理實體 例如X「創建和X的狀態 被複制到新的託管 實體實例X」。

  • 如果X是一個 除去實體實例,一個 IllegalArgumentException將由合併操作來 拋出(或 事務提交將失敗)。

  • 如果X 是一個管理實體,它是由 合併操作忽略,然而, 合併操作級聯到由X的關係 引用 實體,如果這些關係 被註釋與級聯 元素值cascade=MERGEcascade=ALL註釋。

  • 對於所有 實體Y上從X具有級聯元件 值cascade=MERGEcascade=ALL關係 引用,Y 被遞歸合併爲Y」。對於由X引用的所有 這樣的Y,將X'設置爲 引用Y'。 (注意,如果X是 管理,則X是相同的對象 X「)

  • 如果X是一個實體合併到X」, 與另一個實體Y, 其中cascade=MERGEcascade=ALL是基準 未指定,然後從X 相同的關聯的導航「產生一個 參照管理對象Y」與 相同持久標識爲Y.

正如你所看到的,這裏沒有魔法。分離實例的狀態被複制到新創建的託管實例中。由於你的分離的實例有一個空的列表,託管實例也有它。

而且行爲取決於關係的所有權,因爲在數據庫中的表現反映關係的擁有方:

  • 如果Team是擁有方,TeamPlayer S之間的關係將沖洗過程中被破壞(但Player本身會存活,除非你的關係上有orphanRemoval = true)。
  • 否則,Team中的空列表不會影響數據庫。

如果沖洗上下文之前刷新TeamTeam所有屬性由值從數據庫改寫,因此的Player的名單被恢復(因爲玩家的空單還沒有刷新)。

如果在調用refresh()之前調用flush(),並Team是擁有方,將是空的,因爲關係的破壞過程flush()被傳播到數據庫。

+0

axtavt:謝謝你的解釋!只是測試了你提到的所有可能性,現在開始瞭解情況。關於你的語句:「如果你在調用refresh()之前調用flush(),並且Team是擁有者的一方,那麼list將是空的,因爲在flush()期間關係的銷燬會傳播到數據庫」,那將會是這樣的if使用orphanRemoval true。如果不是這樣,那麼這些孩子就會生存下來,並且刷新會在實體的玩家列表中恢復它們再次感謝 ! – bertie 2011-03-10 02:59:16

+0

你使用哪種JPA提供程序?我熟悉Hibernate,沒有JPA,也有合併操作和懶惰集合,當我嘗試從分離的實例中讀取未初始化的集合時,我得到一個異常,而不是一個空集合。我認爲這是提供者的錯誤。作爲解決方案,請在teamPlayer分離之前初始化該集合。 – Oliv 2012-08-28 10:22:56