Hibernate懒加载问题的5种解决方案
**
1、Hibernate基礎(chǔ)
**
Hibernate基礎(chǔ),傳送門
**
2、什么是Hibernate懶加載
**
當(dāng)我們查詢一個對象的時候,在默認(rèn)情況下,返回的只是該對象的代理對象,當(dāng)用戶去使用該對象的屬性時,才會向數(shù)據(jù)庫再一次發(fā)出查詢語句。
例如,有一個對象是Employee,還有一個對象是Department。顯然,對于Employee相對Department來說,是多對一的關(guān)系;而對于Department相對Employee來說,是一對多的關(guān)系。當(dāng)我們查詢Employee對象的時候,如果希望通過employee對象的屬性department查詢到所對應(yīng)的Department,那么是會拋出異常的。這是因為懶加載的存在,在session關(guān)閉之后,hibernate又向數(shù)據(jù)庫發(fā)出一次請求,結(jié)果就拋出異常了。
**
3、懶加載的4種解決方案
**
3.1 顯式初始化(在查詢方法內(nèi)部)
要查詢某員工屬于哪個部門的時候,需要對Department進行預(yù)先查詢
使用語句
Hibernate.initialize(Department.class);3.2 修改對象關(guān)系文件,將lazy改寫lazy=false,即關(guān)閉懶加載
以上兩種方法,確實可以解決問題,但是缺點是無論后面是否使用該對象,hibernate都會向數(shù)據(jù)庫發(fā)出SQL語句請求數(shù)據(jù),造成不必要的性能浪費。
3.3 使用過濾器(web項目)
①獲取session的方式必須使用getCurrentSession
②特殊的關(guān)閉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{ //特殊的關(guān)閉方式 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關(guān)閉的時間,session的生命周期變長。沒有使用該方法之前,session是在查詢完數(shù)據(jù)之后,就被關(guān)閉了;而現(xiàn)在,session的關(guān)閉是在一次web請求的最后才關(guān)閉。
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中的懶加載和急加載的區(qū)別
**
懶加載: FatchType.LAZY :在加載一個實體的時候,不會馬上從數(shù)據(jù)庫中加載,即從數(shù)據(jù)庫中加載到內(nèi)存。
急加載:FatchType.EAGER :在加載一個實體時,會立即從數(shù)據(jù)庫中查詢,與其關(guān)聯(lián)的類也會被同時查詢。
在我們使用@ManyToOne等時,都會被默認(rèn)為急加載。
在hibernate中,我們無論是使用懶加載還是急加載,get方法都會一次加載所有基本數(shù)據(jù)類型屬性的值,而load則不同。
在我們開啟了懶加載之后,load方法只會加載id屬性,所有的非id屬性的訪問操作都不會執(zhí)行。只有id屬性中有實際值(其實就是你調(diào)用load方法時傳的那個),
在session沒有關(guān)閉的之前,如果訪問除id外的其他屬性才會發(fā)sql語句去查詢,我們經(jīng)常犯的一個錯誤就是在當(dāng)前session關(guān)閉以后訪問由load()加載的對象的非id屬性,
此時Hibernate嘗試通過當(dāng)前session發(fā)sql查詢,但發(fā)現(xiàn)session已經(jīng)關(guān)閉,這樣就會發(fā)出no session的異常 。
一般我們將將FetchType.lazy 改成 EAGER ,就可以避免這個錯誤。
但是在我們需要查詢一個表時,如果這個表有很多與其關(guān)聯(lián)的表,如果使用急加載的話,在第一次加載就會很慢,如果是懶加載相對則會快一些。但是在我們又需要查詢與此表相關(guān)的數(shù)據(jù)的時候
急加載就會很快,因為在第一次加載的時候,已經(jīng)幫我們?nèi)考虞d好了。而懶加載則會相對慢一些,因為在我門需要查詢的時候,它才會幫我們?nèi)ゲ椤?/p>
所以讓他們算是各有優(yōu)缺點。
而我們用哪一種方法更好,則需要根據(jù)我們的具體情況去使用了
總結(jié)
以上是生活随笔為你收集整理的Hibernate懒加载问题的5种解决方案的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 用户网购手机激活后要求七天无理由退货,法
- 下一篇: 常用的绝缘材料有哪些