Session.load/get方法均可以根據(jù)指定的實(shí)體類和id從數(shù)據(jù)庫(kù)讀取記錄,并返回與之對(duì)應(yīng)的實(shí)體對(duì)象。其區(qū)別在于:
  1. 如果未能發(fā)現(xiàn)符合條件的記錄,get方法返回null,而load方法會(huì)拋出一個(gè)ObjectNotFoundException。
  2. Load方法可返回實(shí)體的代理類實(shí)例,而get方法永遠(yuǎn)直接返回實(shí)體類。
  3. load方法可以充分利用內(nèi)部緩存和二級(jí)緩存中的現(xiàn)有數(shù)據(jù),而get方法則僅僅在內(nèi)部緩存中進(jìn)行數(shù)據(jù)查找,如沒(méi)有發(fā)現(xiàn)對(duì)應(yīng)數(shù)據(jù),將越過(guò)二級(jí)緩存,直接調(diào)用SQL完成數(shù)據(jù)讀取。

Session在加載實(shí)體對(duì)象時(shí),將經(jīng)過(guò)的過(guò)程:

        首先,Hibernate中維持了兩級(jí)緩存。第一級(jí)緩存由Session實(shí)例維護(hù),其中保持了Session當(dāng)前所有關(guān)聯(lián)實(shí)體的數(shù) 據(jù),也稱為內(nèi)部緩存。而第二級(jí)緩存則存在于SessionFactory層次,由當(dāng)前所有由本SessionFactory構(gòu)造的Session實(shí)例共 享。出于性能考慮,避免無(wú)謂的數(shù)據(jù)庫(kù)訪問(wèn),Session在調(diào)用數(shù)據(jù)庫(kù)查詢功能之前,會(huì)先在緩存中進(jìn)行查詢。首先在第一級(jí)緩存中,通過(guò)實(shí)體類型和id進(jìn)行 查找,如果第一級(jí)緩存查找命中,且數(shù)據(jù)狀態(tài)合法,則直接返回。 之后,Session會(huì)在當(dāng)前“NonExists”記錄中進(jìn)行查找,如果“NonExists”記錄中存在同樣的查詢條件,則返回null。 “NonExists”記錄了當(dāng)前Session實(shí)例在之前所有查詢操作中,未能查詢到有效數(shù)據(jù)的查詢條件(相當(dāng)于一個(gè)查詢黑名單列表)。如此一來(lái),如果 Session中一個(gè)無(wú)效的查詢條件重復(fù)出現(xiàn),即可迅速作出判斷,從而獲得最佳的性能表現(xiàn)。

        對(duì)于load方法而言,如果內(nèi)部緩存中未發(fā)現(xiàn)有效數(shù)據(jù),則查詢第二級(jí)緩存,如果第二級(jí)緩存命中,則返回。 如在緩存中未發(fā)現(xiàn)有效數(shù)據(jù),則發(fā)起數(shù)據(jù)庫(kù)查詢操作(Select SQL),如經(jīng)過(guò)查詢未發(fā)現(xiàn)對(duì)應(yīng)記錄,則將此次查詢的信息在“NonExists”中加以記錄,并返回null。 根據(jù)映射配置和Select SQL得到的ResultSet,創(chuàng)建對(duì)應(yīng)的數(shù)據(jù)對(duì)象。 將其數(shù)據(jù)對(duì)象納入當(dāng)前Session實(shí)體管理容器(一級(jí)緩存)。 執(zhí)行Interceptor.onLoad方法(如果有對(duì)應(yīng)的Interceptor)。 將數(shù)據(jù)對(duì)象納入二級(jí)緩存。 如果數(shù)據(jù)對(duì)象實(shí)現(xiàn)了LifeCycle接口,則調(diào)用數(shù)據(jù)對(duì)象的onLoad方法。 返回?cái)?shù)據(jù)對(duì)象。

另外值得注意的是:(接前面的例子)

        User user1 = (User) session.get(User.class, new Integer(1));
        User user2 = (User) session.load(User.class, new Integer(1));

        User user2 = (User) session.load(User.class, new Integer(1));

        User user1 = (User) session.get(User.class, new Integer(1));
僅僅執(zhí)行的順序不同,但取數(shù)據(jù)使用的機(jī)制是不同的。

如下圖所示:

很明顯,在執(zhí)行session.get之前從來(lái)沒(méi)有執(zhí)行過(guò)session.load,則session.get直接返回實(shí)體而不使用proxy。在這之后若使用session.load也將直接返回實(shí)體。

但是如果由session.load先執(zhí)行,則一定不會(huì)直接返回對(duì)象實(shí)體的。因?yàn)樗麅?yōu)先考慮從緩存中返回?cái)?shù)據(jù)。



ExtJS教程- Hibernate教程-Struts2 教程-Lucene教程