天天看點

struts2異常:Struts Problem Report Struts has detected an unhandled exception: Messages: could not in

今天在寫struts2 項目的時候,我一在jsp頁面(有其他struts2标簽,顯示無誤)中,一輸入struts2的<s:debug></s:debug>标簽,就出現了如下錯誤:(删掉這個标簽後又正常使用)

嚴重: Servlet.service() for servlet jsp threw exception
org.hibernate.LazyInitializationException: could not initialize proxy - no Session
    at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:164)
    at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:285)
    at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:185)
    at com.chenruijia.ssh.entities.Department_$$_javassist_0.toString(Department_$$_javassist_0.java)
    at java.lang.String.valueOf(String.java:2827)
    at java.lang.StringBuffer.append(StringBuffer.java:219)
    at freemarker.ext.beans.SimpleMethodModel.exec(SimpleMethodModel.java:130)
    at freemarker.core.MethodCall._getAsTemplateModel(MethodCall.java:93)
    at freemarker.core.Expression.getAsTemplateModel(Expression.java:89)
    at freemarker.core.Expression.getStringValue(Expression.java:93)
    at freemarker.core.StringBuiltins$StringBuiltIn._getAsTemplateModel(StringBuiltins.java:71)
       ......


           

我就很納悶了,一個struts2的标簽怎麼會影響到hibernate的session呢?

分析:

注意看上面的紅色标記出來的内容(此時發現學好英語真的很重要!),仔細看,大概的意思是懶加載的問題吧,

意思是在session(hibernate裡的session)關閉後使用employee對象的未加載變量,也就是說session已經關閉,然而該執行個體變量卻還沒有被初始化,就使用了該執行個體變量,導緻該異常。      

于是,我專門隻查詢

這個異常的原因,看到了這篇文章  https://www.cnblogs.com/TTTTT/p/6682798.html(應該和我做的是同一個小項目),裡面提到:

由于employee是由hibernate進行加載的,可能hibernate本身是以load的方式将該執行個體變量得到。此時在employeeDao裡session擷取到的是的employee代理類對象,整個Session範圍内,應用程式沒有通路過employee對象,那麼employee代理類的執行個體一直不會被初始話。事務是作用在EmployeeService上,導緻
List<Employee> getAll( )方法調用之前擷取Session、開啟事務,這個方法結束之後送出事務、關閉session。session關閉後,在EmployeeAction擷取employee時是未初始化的employee代理類對象,未被初始化的代理類對象隻有OID其他屬性全為null,那麼放入request的Map裡的是未被初始化的employee代理類對象。一旦在action或者jsp裡要擷取employee代理類對象,必然會發生懶加載異常。同理,在jsp裡擷取employee的department時同樣存在懶加載的問題。      
(關于hiberante的延遲加載,更詳細的在原作者的另一篇部落格裡:http://www.cnblogs.com/TTTTT/p/6682304.html)      

解決辦法:

方法1.用openSessionInView 。
方法2.把這個類的延遲加載禁掉,lazy設為false。
方法3.迫切左外連接配接

      

但是,關鍵在于我已經使用了迫切左外連接配接(在前一個頁面顯示清單資訊的時候已經遇到過這樣的問題,在我的getList()方法中是使用了迫切左外連接配接:

//查詢所有的員工資訊
	public List<Employee> getAll(){
		//迫切左連接配接
		String hql = "FROM Employee e LEFT OUTER JOIN FETCH e.department";
		List<Employee> list = getSession().createQuery(hql).list();
		return list;
	}
           

然後我在希望去對應的修改頁面上時,我使用了get(id)這個方法,在加上<s:debug>标簽後才抛了這個異常。

//查詢單個員工資訊
    public Employee get(Integer id){
        return (Employee) getSession().get(Employee.class,id);
    }
           

于是,我在employee.hbm.xml檔案中,嘗試将其懶加載關掉。

<!-- 映射單向 n-1 的關聯關系 -->
        <many-to-one name="department" class="com.chenruijia.ssh.entities.Department" lazy="false">
            <column name="DEPARTMENT_ID" />
        </many-to-one>
 
           

個人分析:

       确實,解決這種懶加載的問題确實是上面的三個方法,(對于方法2和3)老師推薦我們使用迫切左外連接配接而不是取消懶加載,但是如果需要根據不同的條件去寫方法,每個都用迫切左外連接配接未免太麻煩。我想,在學習過程中,不需要懶加載的情況下也可以直接關閉懶加載,而更加友善,當然,以後實際開發可以用第一種方法或者其他的方法會更加科學。

最後,雖然問題解決了,但是對于之前 “<s:debug>标簽就不行,删掉就好” 的問題,個人水準問題還是沒法解決,可能是<s:debug>内部的機制要求的吧!希望有大神可以指點一下。

結束和聲明

以上純屬個人觀點和體會

希望這篇文章能對你有所幫助!

歡迎大家來一起讨論分享幹貨,或者批評指正!

更加熱切盼望各路大神前輩給些指導和建議!

以後會不定期更新心得和總結,包括學習過程中各種異常和解決辦法等等。再見!

轉載請注明出處!或者聯系我!([email protected])

繼續閱讀