新聞中心
本文主要介紹Hibernate中兩個(gè)極為相似的方法Hibernate get()與Hibernate load(),他們都可以通過(guò)指定的實(shí)體類與ID從數(shù)據(jù)庫(kù)中讀取數(shù)據(jù),并返回對(duì)應(yīng)的實(shí)例,但Hibernate不會(huì)搞兩個(gè)完全一樣的方法的,它們間的不同在于:
◆如果找不到符合條件的紀(jì)錄,get()方法將返回null.而load()將會(huì)報(bào)出ObjectNotFoundEcception.

◆load()方法可以返回實(shí)體的代理類實(shí)例,而get()永遠(yuǎn)只返回實(shí)體類.
◆load()方法可以充分利用二級(jí)緩存和內(nèi)部緩存的現(xiàn)有數(shù)據(jù),而get()方法只在內(nèi)部緩存中進(jìn)行查找,如沒(méi)有發(fā)現(xiàn)對(duì)應(yīng)數(shù)據(jù)將跳過(guò)二級(jí)緩存,直接調(diào)用SQL完成查找.
呵呵,沒(méi)有說(shuō)到根本點(diǎn)上,Hibernate get方法和Hibernate load方法的根本區(qū)別在于:如果你使用load方法,hibernate認(rèn)為該id對(duì)應(yīng)的對(duì)象(數(shù)據(jù)庫(kù)記錄)在數(shù)據(jù)庫(kù)中是一定存在的,所以它可以放心的使用,它可以放心的使用代理來(lái)延遲加載該對(duì)象。在用到對(duì)象中的其他屬性數(shù)據(jù)時(shí)才查詢數(shù)據(jù)庫(kù),但是萬(wàn)一數(shù)據(jù)庫(kù)中不存在該記錄,那沒(méi)辦法,只能拋異常,所說(shuō)的load方法拋異常是指在使用該對(duì)象的數(shù)據(jù)時(shí),數(shù)據(jù)庫(kù)中不存在該數(shù)據(jù)時(shí)拋異常,而不是在創(chuàng)建這個(gè)對(duì)象時(shí)。由于session中的緩存對(duì)于hibernate來(lái)說(shuō)是個(gè)相當(dāng)廉價(jià)的資源,所以在load時(shí)會(huì)先查一下session緩存看看該id對(duì)應(yīng)的對(duì)象是否存在,不存在則創(chuàng)建代理。所以如果你知道該id在數(shù)據(jù)庫(kù)中一定有對(duì)應(yīng)記錄存在就可以使用load方法來(lái)實(shí)現(xiàn)延遲加載。
對(duì)于get方法,hibernate會(huì)確認(rèn)一下該id對(duì)應(yīng)的數(shù)據(jù)是否存在,首先在session緩存中查找,然后在二級(jí)緩存中查找,還沒(méi)有就查數(shù)據(jù)庫(kù),數(shù)據(jù)庫(kù)中沒(méi)有就返回null。
對(duì)于第2點(diǎn),雖然好多書中都這么說(shuō):“get()永遠(yuǎn)只返回實(shí)體類”,但實(shí)際上這是不正確的,get方法如果在session緩存中找到了該id對(duì)應(yīng)的對(duì)象,如果剛好該對(duì)象前面是被代理過(guò)的,如被load方法使用過(guò),或者被其他關(guān)聯(lián)對(duì)象延遲加載過(guò),那么返回的還是原先的代理對(duì)象,而不是實(shí)體類對(duì)象,如果該代理對(duì)象還沒(méi)有加載實(shí)體數(shù)據(jù)(就是id以外的其他屬性數(shù)據(jù)),那么它會(huì)查詢二級(jí)緩存或者數(shù)據(jù)庫(kù)來(lái)加載數(shù)據(jù),但是返回的還是代理對(duì)象,只不過(guò)已經(jīng)加載了實(shí)體數(shù)據(jù)。
胡說(shuō)八道,前面已經(jīng)講了,get方法首先查詢session緩存,沒(méi)有的話查詢二級(jí)緩存,最后查詢數(shù)據(jù)庫(kù);反而load方法創(chuàng)建時(shí)首先查詢session緩存,沒(méi)有就創(chuàng)建代理,實(shí)際使用數(shù)據(jù)時(shí)才查詢二級(jí)緩存和數(shù)據(jù)庫(kù)。
總之對(duì)于get和load的根本區(qū)別,一句話,hibernate對(duì)于load方法認(rèn)為該數(shù)據(jù)在數(shù)據(jù)庫(kù)中一定存在,可以放心的使用代理來(lái)延遲加載,如果在使用過(guò)程中發(fā)現(xiàn)了問(wèn)題,只能拋異常;而對(duì)于get方法,hibernate一定要獲取到真實(shí)的數(shù)據(jù),否則返回null。
樓主有沒(méi)有實(shí)際測(cè)試過(guò),還是道聽(tīng)途說(shuō),還是想混積分。
網(wǎng)上有許多關(guān)于Hibernate get/Hibernate load方法的討論,自己做了一個(gè)小小的實(shí)驗(yàn),明確一下Hibernate get/Hibernate load方法的工作原理。
首先get方法沒(méi)有什么可說(shuō)的,就是在Session執(zhí)行此函數(shù)的時(shí)候hit一下數(shù)據(jù)庫(kù),而load方法比較麻煩,具體的執(zhí)行流程是這樣的:
java 代碼
- Session session=getSessionFactory().openSession();
- Transaction tr=session.beginTransaction();
- //Student stu2=(Student)session.get(Student.class, new Integer(5));
- //if(session.contains(stu2)) System.out.println("stu2 in the session");
- Student stu=(Student)session.load(Student.class, new Integer(5));
- stu.getAddress();
- tr.commit();
- session.close();
(1)查找Session所在的persistent Context中是否有緩存的persistent object,如果有則直接返回該persistent object作為stu對(duì)象;如果沒(méi)有,則需要建立代理對(duì)象,該代理對(duì)象不是我們認(rèn)為的pojo,其中的代理對(duì)象的initialized屬性為false,target屬性為null。
(2)在訪問(wèn)獲得的代理對(duì)象的屬性時(shí),例如執(zhí)行stu.getArress()時(shí),因?yàn)榇藭r(shí)的persistent Context中沒(méi)有該persistent object,所以會(huì)hit數(shù)據(jù)庫(kù)。
(3)hit數(shù)據(jù)庫(kù)時(shí),如果在數(shù)據(jù)庫(kù)中找到該對(duì)象對(duì)應(yīng)的記錄,那么用獲得的對(duì)象賦值給該代理對(duì)象的target屬性,并且將initialized屬性改為true;如果在數(shù)據(jù)庫(kù)中找不到該對(duì)象對(duì)應(yīng)的記錄,那么拋出org.hibernate.ObjectNotFoundException異常。
而get方法每次執(zhí)行都hit數(shù)據(jù)庫(kù),如果沒(méi)有相對(duì)應(yīng)的記錄,那么就返回null。
1)當(dāng)數(shù)據(jù)庫(kù)不存在對(duì)應(yīng)ID數(shù)據(jù)時(shí),調(diào)用load()方法將會(huì)拋出ObjectNotFoundException異常,get()方法將返回null.下面是一個(gè)簡(jiǎn)單的測(cè)試數(shù)據(jù)庫(kù)中沒(méi)有id為2的person
2)也就是延時(shí)加載的區(qū)別。load的方法默認(rèn)要加載的對(duì)象是存在數(shù)據(jù)庫(kù)中的,返回的是一個(gè)代理對(duì)象而不是一個(gè)真正的類實(shí)例,當(dāng)用到具體與數(shù)據(jù)庫(kù)有關(guān)的數(shù)據(jù)時(shí)候才查詢數(shù)據(jù)庫(kù),而get方法直接查詢數(shù)據(jù)庫(kù),返回類的實(shí)例。例如上面的例子,運(yùn)行到(1)直接輸出sql語(yǔ)句,而(3)卻沒(méi)有輸出,在(5)輸出了一條sql語(yǔ)句,由于所查詢的對(duì)象不存在拋出ObjectNotFoundException異常。關(guān)于類的代理對(duì)象可以通過(guò)debug調(diào)試的到。但是如果在內(nèi)部?jī)?nèi)存中存在所要查詢的對(duì)象,無(wú)論對(duì)象是代理的(load出來(lái)的)還是類的實(shí)例(get出來(lái)的)都會(huì)返回內(nèi)存中的形態(tài)。
3)第三點(diǎn)區(qū)別就是:“,get方法首先查詢session緩存,沒(méi)有的話查詢二級(jí)緩存,最后查詢數(shù)據(jù)庫(kù);反而load方法創(chuàng)建時(shí)首先查詢session緩存,沒(méi)有就創(chuàng)建代理,實(shí)際使用數(shù)據(jù)時(shí)才查詢二級(jí)緩存和數(shù)據(jù)庫(kù)?!边@是從別的地方聽(tīng)說(shuō)的。
新聞名稱:對(duì)Hibernate中g(shù)et()與load()不同點(diǎn)分析
標(biāo)題URL:http://www.5511xx.com/article/cdgpihs.html


咨詢
建站咨詢
