當使用hibernate查詢一個對象的時候,如果Session關閉,再調用該對象關聯的集合或者對象的時候,會產生懶加載異常!
方案一:
在Session關閉之前,查詢對象關聯的集合或者對象,所有在業務層的方法上添加:
1 public ElecUser findUserByLogonName(String name) { 2 3 String condition = " and o.logonName = ?"; 4 5 Object [] params = {name}; 6 7 List<ElecUser> list = elecUserDao.findCollectionByConditionNoPage(condition, params, null); 8 9 //數據庫表中存在該用戶,返回ElecUser對象 10 11 ElecUser elecUser = null; 12 13 if(list!=null && list.size()>0){ 14 15 elecUser = list.get(0); 16 17 } 18 19 /*** 20 21 * 解決懶加載異常 22 23 除了OID之外的其他屬性 24 25 */ 26 27 elecUser.getElecRoles().size(); 28 29 return elecUser; 30 31 } View Code
方案二:在Service層的方法中(Session關閉之前),初始化對象關聯的集合或者對象
1 public ElecUser findUserByLogonName(String name) { 2 3 String condition = " and o.logonName = ?"; 4 5 Object [] params = {name}; 6 7 List<ElecUser> list = elecUserDao.findCollectionByConditionNoPage(condition, params, null); 8 9 //數據庫表中存在該用戶,返回ElecUser對象 10 11 ElecUser elecUser = null; 12 13 if(list!=null && list.size()>0){ 14 15 elecUser = list.get(0); 16 17 } 18 19 /*** 20 21 * 解決懶加載異常 22 23 */ 24 25 Hibernate.initialize(elecUser.getElecRoles()); 26 27 return elecUser; 28 29 } View Code
方案三:在ElecUser.hbm.xml中,添加lazy=”false”,查詢用戶的同時,立即檢索查詢用戶關聯的角色集合:
1 <set name="elecRoles" table="elec_user_role" inverse="true" lazy="false"> 2 3 <key> 4 5 <column name="userID"></column> 6 7 </key> 8 9 <many-to-many class="cn.itcast.elec.domain.ElecRole" column="roleID"/> 10 11 </set> View Code表示查詢用戶的時候,立即檢索用戶所關聯的角色
建議項目開發中不要在.hbm.xml中添加過多的lazy=false,這樣如果表關聯比較多,不需要查詢的對象也被加載了,性能會出現問題。
方案四:使用spring提供的過濾器OpenSessionInViewFilter,在web容器中添加該過濾器
在web.xml中添加:
要求:該過濾器一定要放置到strtus2的過濾器的前面,先執行該過濾器。
1 <!-- 添加spring提供的過濾器,解決hibernate的懶加載問題 --> 2 3 <filter> 4 5 <filter-name>OpenSessionInViewFilter</filter-name> 6 7 <filter-class> 8 9 org.springframework.orm.hibernate3.support.OpenSessionInViewFilter 10 11 </filter-class> 12 13 </filter> 14 15 <filter-mapping> 16 17 <filter-name>OpenSessionInViewFilter</filter-name> 18 19 <url-pattern>*.do</url-pattern> 20 21 <url-pattern>*.jsp</url-pattern> 22 23 </filter-mapping> 24 25 <!-- 配置struts2的過濾器,這是struts2運行的核心 --> 26 27 <filter> 28 29 <filter-name>struts2</filter-name> 30 31 <filter-class> 32 33 org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter 34 35 </filter-class> 36 37 </filter> 38 39 <filter-mapping> 40 41 <filter-name>struts2</filter-name> 42 43 <url-pattern>*.do</url-pattern> 44 45 <url-pattern>*.jsp</url-pattern> 46 47 </filter-mapping> View CodeOpenSessionInViewFilter過濾器實現的原理:
1:事務提交:spring提供的聲明式事務控制,仍然在業務層的方法進行處理,方法執行完畢後,事務會自動提交,如果出現異常,事務就會回滾。但是它延遲了Session關閉的時間。
2:Session關閉:Session在頁面上進行關閉,此時當頁面上的數據加載完成之後,再關閉Session。
問題:
如果你開發的系統對頁面數據加載比較大的時候,不適合使用OpenSessionInViewFilter,這樣Session不能及時關閉,另一個Session就無法訪問,連接不夠使用,就會產生“假死”現象。