1. 程式人生 > >Hibernate中could not initialize proxy

Hibernate中could not initialize proxy

[i]轉載自:[url]http://blog.csdn.net/remote_roamer/article/details/2934437[/i][/url]

異常:
org.hibernate.LazyInitializationException: could not initialize proxy - no Session
at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:57)
at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:111)

[b]原因:hibernate3 many-to-one的預設選項是 lazy = "proxy"
解決方法:<many-to-one> & <set> 中設定 lazy="false"[/b]


HIBERNATE的持久化物件載入策略。
延遲載入, 也就是用到的時候才去載入.這樣可以提高一些效能.
Hibernate的lazy loading 採用了一個HibernateSession來管理session,它的邏輯是每進行一次資料庫操作,就開新的session,操作完成後立即關閉該session。這樣做的好處是可以嚴格關閉session,避免菜鳥級的錯誤,但是hibernate.org並不推薦這麼做。因為這不適合lazy loading,也不適合跨方法的事務。

比如在我們的應用中,user->post形成一對多的對映,User中有一個包含post的List。
在User中,有多個屬性:name,password,phone等,還有一個List型別的posts。當我們對posts使用lazy laoding的時候,hibernate會在獲得User物件的時候,僅僅返回name,password,phone等基本屬性,當你訪問posts的時候,它才會從資料庫中提取posts需要的資料,這就是所謂lazy laoding。但是在我們的系統中,session是被立即關閉的,也就是在讀取了name,password,phone等基本屬性後,session已經close了,再進行lazy loaiding就會有異常。
解決辦法是在close session之前,呼叫Hibernate.initialize(user.getPosts()),告訴系統,user.getPosts()是需要lazy laoding的。但是這樣做會破壞HibernateSession類的封裝.
後來採用所謂的OpenSessionInView模式,把session的週期交給servlet filter來管理,每當有request進來,就開啟一個session,response結束之後再關閉它,這樣可以讓session存在於整個請求週期中。

Hibernate中Lazy延遲載入
Hibernate有關one-to-one和many-to-one在查詢中的父親端lazy問題
Hibernate3在關聯上有lazy這個屬性,如果是Hibernate2,應該是設定outer-join="false",然後被關聯的物件,在class那個地方設定lazy="true".首先,對於many-to-one的問題,可以在父親端的class標籤中設定lazy來解決,這樣,在查詢兒子的時候,不會發送多餘的sql .
對於one-to-one,在hibernate2裡面,由於one-to-one裡面沒有lazy的選項,所以只能通過設定outer-join="false"來解決。而hibernate3已經加入了lazy,所以不會有這個問題。
總體來說,如果你發現你查詢兒子的時候,有多餘的sql傳送,那一定是你對hibernate的誤用..

在hibernate 的one-to-many,many-to-one,many-to-many中,為了效率的提高,我們一般都採用lazy機制,但使用spring的getHibernateTemplate().save(Object)時,HibernateTemplate試圖每次在execute之前去獲得Session,執行完就力爭關閉Session 。也就是說Hibernate的Lazy初始化1:n關係時,你必須保證是在同一個Session內部使用這個關係集合,不然Hiernate將丟擲Failed to lazily initialize a collection - no session or session was closed的例外。


Hibernate中的物件的關聯(association)的設定還是不夠靈活,實際應用中有的地方需要lazy load,有的地方又不需要,其實還有的地方就根本不需要使用association。而在Hibernate中,只能在影射檔案中設定一種方式,像我們這樣的應用,我是不敢輕易使用open session in view的(慢點總比lock住要好),只能是要麼不設定association,要麼就是lazy=true的。以前的分類資訊只用了一個many to one的關係,代價還可以忍受,但現在關係越來越複雜了,再多加幾個的話,所要付出的performance,頻寬等方面的代價恐怕就不能忽略了,即使使用cache提高一點performance,對頻寬的浪費也還是不可原諒的。