Session.load/get方法均可以根據指定的實(shí)體類(lèi)和id從數據庫讀取記錄,并返回與之對應的實(shí)體對象。其區別在于:
- 如果未能發(fā)現符合條件的記錄,get方法返回null,而load方法會(huì )拋出一個(gè)ObjectNotFoundException。
- Load方法可返回實(shí)體的代理類(lèi)實(shí)例,而get方法永遠直接返回實(shí)體類(lèi)。
- load方法可以充分利用內部緩存和二級緩存中的現有數據,而get方法則僅僅在內部緩存中進(jìn)行數據查找,如沒(méi)有發(fā)現對應數據,將越過(guò)二級緩存,直接調用SQL完成數據讀取。
Session在加載實(shí)體對象時(shí),將經(jīng)過(guò)的過(guò)程:
- 首先,Hibernate中維持了兩級緩存。第一級緩存由Session實(shí)例維護,其中 保持了Session當前所有關(guān)聯(lián)實(shí)體的數據,也稱(chēng)為內部緩存。而第二級緩存則存在于SessionFactory層次,由當前所有由本 SessionFactory構造的Session實(shí)例共享。出于性能考慮,避免無(wú)謂的數據庫訪(fǎng)問(wèn),Session在調用數據庫查詢(xún)功能之前,會(huì )先在緩存 中進(jìn)行查詢(xún)。首先在第一級緩存中,通過(guò)實(shí)體類(lèi)型和id進(jìn)行查找,如果第一級緩存查找命中,且數據狀態(tài)合法,則直接返回。
- 之 后,Session會(huì )在當前“NonExists”記錄中進(jìn)行查找,如果“NonExists”記錄中存在同樣的查詢(xún)條件,則返回null。 “NonExists”記錄了當前Session實(shí)例在之前所有查詢(xún)操作中,未能查詢(xún)到有效數據的查詢(xún)條件(相當于一個(gè)查詢(xún)黑名單列表)。如此一來(lái),如果 Session中一個(gè)無(wú)效的查詢(xún)條件重復出現,即可迅速作出判斷,從而獲得最佳的性能表現。
- 對于load方法而言,如果內部緩存中未發(fā)現有效數據,則查詢(xún)第二級緩存,如果第二級緩存命中,則返回。
- 如在緩存中未發(fā)現有效數據,則發(fā)起數據庫查詢(xún)操作(Select SQL),如經(jīng)過(guò)查詢(xún)未發(fā)現對應記錄,則將此次查詢(xún)的信息在“NonExists”中加以記錄,并返回null。
- 根據映射配置和Select SQL得到的ResultSet,創(chuàng )建對應的數據對象。
- 將其數據對象納入當前Session實(shí)體管理容器(一級緩存)。
- 執行Interceptor.onLoad方法(如果有對應的Interceptor)。
- 將數據對象納入二級緩存。
- 如果數據對象實(shí)現了LifeCycle接口,則調用數據對象的onLoad方法。
- 返回數據對象。