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