Hibernate懒加载问题的5种解决方案
**
1、Hibernate基礎
**
Hibernate基礎,傳送門
**
2、什么是Hibernate懶加載
**
當我們查詢一個對象的時候,在默認情況下,返回的只是該對象的代理對象,當用戶去使用該對象的屬性時,才會向數據庫再一次發出查詢語句。
例如,有一個對象是Employee,還有一個對象是Department。顯然,對于Employee相對Department來說,是多對一的關系;而對于Department相對Employee來說,是一對多的關系。當我們查詢Employee對象的時候,如果希望通過employee對象的屬性department查詢到所對應的Department,那么是會拋出異常的。這是因為懶加載的存在,在session關閉之后,hibernate又向數據庫發出一次請求,結果就拋出異常了。
**
3、懶加載的4種解決方案
**
3.1 顯式初始化(在查詢方法內部)
要查詢某員工屬于哪個部門的時候,需要對Department進行預先查詢
使用語句
Hibernate.initialize(Department.class);3.2 修改對象關系文件,將lazy改寫lazy=false,即關閉懶加載
以上兩種方法,確實可以解決問題,但是缺點是無論后面是否使用該對象,hibernate都會向數據庫發出SQL語句請求數據,造成不必要的性能浪費。
3.3 使用過濾器(web項目)
①獲取session的方式必須使用getCurrentSession
②特殊的關閉session方式
public void doFilter(ServletRequest request, ServletResponse response, FilterChain arg2) throws IOException, ServletException { // TODO Auto-generated method stub Session session = null; Transaction tx = null; try { session = HibernateUtil.getCurrentSession(); tx = session.beginTransaction(); arg2.doFilter(request, response);//請求一直在走 tx.commit(); } catch (Exception e) { // TODO: handle exception if(tx != null){ tx.rollback(); } }finally{ //特殊的關閉方式 HibernateUtil.closeCurrentSession(); } }3.4 在SSH框架中,使用spring提供的openSessionView
其原理和第三種方法中使用Filter類似,只不過這個filter是spring提供的。使用時只需要在web.xml文件配置如下:
<!-- 使用spring解決懶加載問題 --> <filter> <filter-name>OpenSessionInViewFilter</filter-name> <filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class> </filter> <filter-mapping> <filter-name>OpenSessionInViewFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>第3和第4中方法也能解決懶加載的問題,其中第4種方法也是目前使用較多的。但是這兩種方法也是有缺點的,缺點就是延長了session關閉的時間,session的生命周期變長。沒有使用該方法之前,session是在查詢完數據之后,就被關閉了;而現在,session的關閉是在一次web請求的最后才關閉。
3.5 將hibernate的抓取策略改為join
,也就是left join fetch 或inner join fetch語法, 就是在<many-to-one …/>中配置lazy=“false” fetch=“join” 即可。如:
<many-to-one name="worker" lazy="false" fetch="join" class="com.paixie.dpmain.Worker"><column name="positionId"></column></many-to-one>**
4、hibernate中的懶加載和急加載的區別
**
懶加載: FatchType.LAZY :在加載一個實體的時候,不會馬上從數據庫中加載,即從數據庫中加載到內存。
急加載:FatchType.EAGER :在加載一個實體時,會立即從數據庫中查詢,與其關聯的類也會被同時查詢。
在我們使用@ManyToOne等時,都會被默認為急加載。
在hibernate中,我們無論是使用懶加載還是急加載,get方法都會一次加載所有基本數據類型屬性的值,而load則不同。
在我們開啟了懶加載之后,load方法只會加載id屬性,所有的非id屬性的訪問操作都不會執行。只有id屬性中有實際值(其實就是你調用load方法時傳的那個),
在session沒有關閉的之前,如果訪問除id外的其他屬性才會發sql語句去查詢,我們經常犯的一個錯誤就是在當前session關閉以后訪問由load()加載的對象的非id屬性,
此時Hibernate嘗試通過當前session發sql查詢,但發現session已經關閉,這樣就會發出no session的異常 。
一般我們將將FetchType.lazy 改成 EAGER ,就可以避免這個錯誤。
但是在我們需要查詢一個表時,如果這個表有很多與其關聯的表,如果使用急加載的話,在第一次加載就會很慢,如果是懶加載相對則會快一些。但是在我們又需要查詢與此表相關的數據的時候
急加載就會很快,因為在第一次加載的時候,已經幫我們全部加載好了。而懶加載則會相對慢一些,因為在我門需要查詢的時候,它才會幫我們去查。
所以讓他們算是各有優缺點。
而我們用哪一種方法更好,則需要根據我們的具體情況去使用了
總結
以上是生活随笔為你收集整理的Hibernate懒加载问题的5种解决方案的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 用户网购手机激活后要求七天无理由退货,法
- 下一篇: Hibernate与MyBatis对比