Hibernate - cannot simultaneously fetch multiple bags 異常

......
cannot simultaneously fetch multiple bags異常是由於持久層實時加載太多異同對象而致。例如用戶登錄時,同步實時加載用戶的角色對象、權限對象,而往往這些關係都是多對多關係,就單一列內容來看存在重複的值,從而引起multiple bags。我在網上搜索這類結果,幾乎都提出一個解決辦法——採用延遲加載,即fetch=FetchType.LAZY,這樣就束縛了框架的強大功能,也有提過用@IndexColumn解決,但@IndexColumn是Hibernate的東西,不是JPA規範(下文有討論)。既要實時加載,又保證不會出現主題問題,這就是本文所要探討的。


JPA規範中,一對多或多對多的多方數據抓取過來後必須用容器類存,例如Set、List、Map等,初學者可能沒有對這個幾個容器認真研究,隨便拿一個就用。事實上這幾個容器有很大的區別,本文不具體討論這些容器的區別和功能,但提一個特別要注意的區別——導致本文主題的產生——就是容器內是否允許重複值,那讓們簡單地瞭解下這此容器的特性:


Set:
      _Set中不允許存放重複元素;
      _Set中的元素是無序的。
List:
      _List中可以存放重複元素;
      _List中的元素是一個有序的集合,可以通過索引訪問List中的元素。
Map:
      _Map是以鍵/值存放數據,因此它有較高的存取性能;
      _Map中不允許重複的鍵,但可以有重複的值


有了這些區別,我們就可以開始尋找主題問題,當持久框架抓取一方的對象時,同時加載多方的對象放進容器中,多方又可能與關聯其它對象,Hibernate 實現的JPA,默認最高抓取深度含本身級爲四級(它有個屬性配置是0-3),若多方(第二級)存在重複值,則第三級中抓取的值就無法映射,按照這個道理,就應該報出無法同時加載多個包之異常。由於國內EJB3.0以後的教材是少而甚少,更沒有較完善的JPA手冊,所以筆者這樣的理解可能會引起質疑,但事實上,筆者是通過這個思路解決了問題:
即@ManyToMany或@OneToMany的Many方此時一定用Set容器來存放,而不能用List集合。


不過Hibernate有些功能超越了JPA規範,它支持真正的List集合,映射集合的方式和以前完全一樣,只不過要新增 @IndexColumn註解, 該註解允許你指明存放索引值的字段。但實際上是創建唯一性索引,抓取多方的結果也是唯一的,就是上述 Set容器不允許重複元素的道理一樣。


出現此異常的讀者,先看看自己是不是用了List集合而導致此問題的發生,若是用Set還出現此問題,則去看Set容器內的對象的類中是不是還有類似問題。





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章