1. 程式人生 > >使用@ManyToOne並延時加載出現的問題以及解決總結

使用@ManyToOne並延時加載出現的問題以及解決總結

使用HIBERNATE的註解@ManyToOne(fetch = FetchType.lazy) 時候,報出錯誤


org.hibernate.LazyInitializationException: could not initialize proxy - no Session
at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:167)
at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:215)
at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:190)
at com.evolution.warlock.entity.Department_$$_javassist_1.getName(Department_$$_javassist_1.java)
at org.apache.shiro.authc.pam.ModularRealmAuthenticator.doSingleRealmAuthentication(ModularRealmAuthenticator.java:180)
at org.apache.shiro.authc.pam.ModularRealmAuthenticator.doAuthenticate(ModularRealmAuthenticator.java:267)
at org.apache.shiro.authc.AbstractAuthenticator.authenticate(AbstractAuthenticator.java:198)


找了下答案,主要是因為:

fetch=FetchType.LAZY就等於打開了延遲載入,Hibernate中的get方法不論是否開啟延遲載入都會一次載入所有基本資料型別屬性的值,而load則不同,開啟延遲載入後load(id),返回的物件會被Hibernate加一個殼(持久化上下文中沒有快取該物件的前提下),攔截所有非id屬性的訪問操作(getter,setter呼叫),只有id屬性中有實際值(其實就是你呼叫load方法時傳的那個),在session沒有關閉的之前,如果訪問除id外的其他屬性才會發sql語句去查詢,你這個錯誤就是因為在當前session關閉以後訪問由load()載入的物件的非id屬性,此時Hibernate嘗試通過當前session發sql查詢,但發現session已經關閉,這樣才會報錯。


我測試發現的確是上面所說的,LAZY阻擋了除ID以外的所有訪問,所以解決的辦法就很多,
一.就是隻拿ID,再從資料庫從新拿一次你需要的東西。
二.將FetchType.lazy 改成 EAGER
三.配置xml (沒試過)

<filter>
<filter-name>openSessionInView</filter-name>
<filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
</filter>

<filter-mapping>
<filter-name>openSessionInView</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

四.在service層使用Hibernate.initialize()將你需要的物件從新持久化

五.在MVC裡面配置,個人覺得這個辦法更好