今天搞了一上午,都在解決這個問題:org.hibernate.LazyInitializationException: failed to lazily initialize
原因很簡單,是在非法的session中去調用lazy=“true“的屬性,
網上資料蠻多的,解決方法有兩個
1,把lazy=”false“
2,在web.xml中加入:(在structs的過濾器之前)
<filter> <filter-name>hibernateFilter</filter-name> <filter-class> org.springframework.orm.hibernate.support.OpenSessionInViewFilter </filter-class> </filter> <filter-mapping> <filter-name>hibernateFilter</filter-name> <url-pattern>*.do</url-pattern> </filter-mapping> <!-- 加入上面這些 --> <filter> <filter-name>struts2</filter-name> <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class> </filter> <filter-mapping> <filter-name>struts2</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
第一種方法,就是設置為不要用lazy加載元素,這樣做,雖然可以解決上面這個問題,但是會產生一些不必要的開銷。比較復雜的對象對應關系,或者數據量比較大的時候,不推薦這么做
第二種方法,就是避免session關閉過早導致出現這樣的異常,這樣的方法以前也是使用過,而且一般情況下filter過濾鏈接都會做。
但是以上這兩種方法,在解決小規模的數據時 ,還湊活能用,但是在大量數據時 ,就會產生大量的耗時。
下面說說,我遇到的問題吧,先說前提:
有員工Staff和所在部門Group兩個對象,他們是many-to-many的關系,一個員工可以在多個部門中(比如,甲可以是銷售部門的,也可以同時是人事部門的);一個小組里面有多個員工,如果采用上面兩種解法,就會導致下面這樣的事情發生:
當我在查詢 Staff 甲 時,會再查詢 甲所在的部門A,B,C,D,因為之前設置的兩種方法,會在我們實例化一個對象的時候,將其中lazy加載的所有元素都實例化,也就是會造成,系統會去實例化A,B,C,D部門下的所有員工,這些員工又在別的一些部門中,依次直至所有的對象都被實例化出來,導致相當的耗時。
(不要問我為什么知道,說多了,都是淚啊!!)
最后經過排查,發現是因為兩句log ,也就是我在獲取對象后,用了一句
System.out.println("staff="+staff);
當系統執行這么一句的時候,是會去實例化staff對象里面的所有元素,但是因為staff里面的group是lazy加載的,所以,此時才會出現之前提到過的這個exception.
所以,記住,有lazy加載的對象時,千萬不能用=這個操作,不然必報這個exception