Hibernate載入資料時get和load方法的區別,讓我們先看一下方法原型吧:
1.get方法
/**
* Return the persistent instance of the given entity class with the given identifier,
* or null if there is no such persistent instance. (If the instance, or a proxy for the
* instance, is already associated with the session, return that instance or proxy.)
*
* @param clazz a persistent class
* @param id an identifier
* @return a persistent instance or null
* @throws HibernateException
*/
public Object get(Class clazz, Serializable id) throws HibernateException;
2.load方法
/**
* Return the persistent instance of the given entity class with the given identifier,
* assuming that the instance exists.
* <br><br>
* You should not use this method to determine if an instance exists (use <tt>get()</tt>
* instead). Use this only to retrieve an instance that you assume exists, where non-existence
* would be an actual error.
*
* @param theClass a persistent class
* @param id a valid identifier of an existing persistent instance of the class
* @return the persistent instance or proxy
* @throws HibernateException
*/
經過比較我們可以發現:Session.load/get方法均可以根據指定的實體類和id從資料庫讀取記錄,並返回與之對應的實體物件。其區別在於:
- 如果未能發現合格記錄,get方法返回null,而load方法會拋出一個ObjectNotFoundException。
- Load方法可返回實體的代理類執行個體,而get方法永遠直接返回實體類。
- load方法可以充分利用內部緩衝和二級緩衝中的現有資料,而get方法則僅僅在內部緩衝中進行資料尋找,如沒有發現對應資料,將越過二級緩衝,直接調用SQL完成資料讀取。
Session在載入實體物件時,將經過的過程:
- 首先,Hibernate中維持了兩級緩衝。第一級緩衝由Session執行個體維護,其中保持了Session當前所有關聯實體的資料,也稱為內部緩衝。而第二級緩衝則存在於SessionFactory層次,由當前所有由本SessionFactory構造的Session執行個體共用。出於效能考慮,避免無謂的資料庫訪問,Session在調用資料庫查詢功能之前,會先在緩衝中進行查詢。首先在第一級緩衝中,通過實體類型和id進行尋找,如果第一級緩衝尋找命中,且資料狀態合法,則直接返回。
- 之後,Session會在當前“NonExists”記錄中進行尋找,如果“NonExists”記錄中存在同樣的查詢條件,則返回null。“NonExists”記錄了當前Session執行個體在之前所有查詢操作中,未能查詢到有效資料的查詢條件(相當於一個查詢黑名單列表)。如此一來,如果Session中一個無效的查詢條件重複出現,即可迅速作出判斷,從而獲得最佳的效能表現。
- 對於load方法而言,如果內部緩衝中未發現有效資料,則查詢第二級緩衝,如果第二級快取命中,則返回。
- 如在緩衝中未發現有效資料,則發起資料庫查詢操作(Select SQL),如經過查詢未發現對應記錄,則將此次查詢的資訊在“NonExists”中加以記錄,並返回null。
- 根據映射配置和Select SQL得到的ResultSet,建立對應的資料對象。
- 將其資料對象納入當前Session實體管理容器(一級緩衝)。
- 執行Interceptor.onLoad方法(如果有對應的Interceptor)。
- 將資料對象納入二級緩衝。
- 如果資料對象實現了LifeCycle介面,則調用資料對象的onLoad方法。
- 返回資料對象。