那麼,爲何會出現這個異常呢?web
究其緣由,居然是Hibernate的懶加載引發的。必定是你傳遞的數據中有引用類型的數據採用了懶加載機制。ajax
好比:我要從Action中向前臺傳送一個Collection<Menuitem>,經過get方法sql
public Collection<Menuitem> getMenuitemList() {
return this.menuitemList;
}json
而其中Menuitem類型的數據結構是:數據結構
public class Menuitem {
private Long mid;
private Long pid;//父節點
private String name;//樹的節點的名稱
private Boolean isParent;//是否爲父節點
private String icon;//圖標的路徑
private Boolean checked;//複選框是否被選中
/**
* 菜單權限與用戶是多對多的關係
*/
private Set<User> users;dom
//getter(),setter()方法ui
}this
在映射文件Menuitem.hbm.xml中users屬性的配置以下:spa
<set name="users" table="user_menuitem" inverse="true">
<key column="mid"></key>
<many-to-many column="uid" class="cn.myoa.domain.User"></many-to-many>
</set>插件
未設置lazy="false",則默認採用懶加載模式。
當中間表user_menuitem中沒有數據時,ok,不會牽涉到use表,也就不存在懶加載問題,運行一切正常。
可是當user_menuitem表中有數據,且數據與所傳送的Menuitem對象有關時,就會有問題了
由於懶加載,這樣在Action中獲取的Menuitem對象中的users屬性中的set集合中會存在user對象的引用,可是user的信息其實並未加載,
只有當用到時,容器纔再次發出sql請求進行加載,可是在json插件對menuitemList進行處理以轉換成json格式時,Hibernate Session早已關閉,這樣user信息便加載不成功,而它又沒法對set集合中空的引用進行處理,因此便拋出了JSONException。
有人可能會有疑問,我在web.xml中配置了OpenSessionInViewFilter過濾器,爲何Session還會關閉呢!?
這個疑問問的好!!我也不知何故,在網上也沒找到相關的解釋,不知是否是ajax的XMLHttpRequest的問題,
總之,在struts2與ajax結合的過程當中,OpenSessionInView模式不起做用了!請知道的朋友不吝賜教!
好!既然知道了問題的緣由,那麼解決方法就很明瞭了!
方法一:設置lazy="false",即對user不採用懶加載。如
<set name="users" table="user_menuitem" inverse="true"lazy="false">
<key column="mid"></key>
<many-to-many column="uid" class="cn.myoa.domain.User"></many-to-many>
</set>
不過這時要注意在User對象中有沒有其餘對象的引用,用過有,也要設置爲非懶加載模式。
方法二:忽略set<User> users 屬性,(推薦使用)
若是在前臺頁面不須要使用該屬性的話,就不要把他傳到前臺去,設置方法是在其getter方法上加一註解: @JSON(serialize=false)
@JSON(serialize=false)
public Set<User> getUsers() {
return users;
}
這樣json插件在轉換數據時就會忽略該屬性。
如今問題應該已經解決了!!
下面關於struts2和ajax的結合還有幾點建議:
一、在頁面用不到的數據最好不要傳到前臺(這也是之因此推薦第二種方法的緣由,傳的數據越大,效率越低不是嗎!)
二、不是向前臺傳數據的方法最好不要以get開頭,json插件會把全部get開頭的方法當作屬性,轉爲json格式數據
三、若是方法必須以get開頭,然而又不是爲了轉爲json格式,那麼能夠在該方法上加註解:@JSON(serialize=false)
四、須要傳到前臺的數據,必定要在dao中加載完畢,不能使用懶加載模式。