Hibernate查詢方法與緩存的關(guān)系
在開發(fā)中,通常是通過兩種方式來執(zhí)行對(duì)數(shù)據(jù)庫(kù)的查詢操作的。一種方式是通過ID來獲得單獨(dú)的Java對(duì)象,另一種方式是通過HQL語句來執(zhí)行對(duì)數(shù)據(jù)庫(kù)的查詢操作。下面就分別結(jié)合這兩種Hibernate查詢方法來說明一下緩存的作用。
通過ID來獲得Java對(duì)象可以直接使用Session對(duì)象的load()或者get()方法,這兩種方式的區(qū)別就在于對(duì)緩存的使用上。 下面我們來具體看看Hibernate查詢方法的實(shí)現(xiàn)。
load()方法
在使用了二級(jí)緩存的情況下,使用load()方法會(huì)在二級(jí)緩存中查找指定的對(duì)象是否存在。
在執(zhí)行l(wèi)oad()方法時(shí),Hibernate首先從當(dāng)前Session的一級(jí)緩存中獲取ID對(duì)應(yīng)的值,在獲取不到的情況下,將根據(jù)該對(duì)象是否配置了二級(jí)緩存來做相應(yīng)的處理。
如配置了二級(jí)緩存,則從二級(jí)緩存中獲取ID對(duì)應(yīng)的值,如仍然獲取不到則還需要根據(jù)是否配置了延遲加載來決定如何執(zhí)行,如未配置延遲加載則從數(shù)據(jù)庫(kù)中直接獲 取。在從數(shù)據(jù)庫(kù)獲取到數(shù)據(jù)的情況下,Hibernate會(huì)相應(yīng)地填充一級(jí)緩存和二級(jí)緩存,如配置了延遲加載則直接返回一個(gè)代理類,只有在觸發(fā)代理類的調(diào)用 時(shí)才進(jìn)行數(shù)據(jù)庫(kù)的查詢操作。
在Session一直打開的情況下,并在該對(duì)象具有單向關(guān)聯(lián)維護(hù)的時(shí)候,需要使用類似Session.clear(),Session.evict()的方法來強(qiáng)制刷新一級(jí)緩存。
get()方法
get()方法與load()方法的區(qū)別就在于不會(huì)查找二級(jí)緩存。在當(dāng)前Session的一級(jí)緩存中獲取不到指定的對(duì)象時(shí),會(huì)直接執(zhí)行查詢語句從數(shù)據(jù)庫(kù)中獲得所需要的數(shù)據(jù)。
在Hibernate查詢方法中,可以通過HQL來執(zhí)行對(duì)數(shù)據(jù)庫(kù)的查詢操作。具體的查詢是由Query對(duì)象的list()和iterator()方法來執(zhí)行的。這兩個(gè)方法在執(zhí)行查詢時(shí)的處理方法存在著一定的差別,在開發(fā)中應(yīng)該依據(jù)具體的情況來選擇合適的方法。
list()方法
在執(zhí)行Query的list()方法時(shí),Hibernate查詢方法是首先檢查是否配置了查詢緩存,如配置了則從查詢緩存中尋找是否已經(jīng)對(duì)該查詢進(jìn)行了緩 存,如獲取不到則從數(shù)據(jù)庫(kù)中進(jìn)行獲取。從數(shù)據(jù)庫(kù)中獲取到后,Hibernate將會(huì)相應(yīng)地填充一級(jí)、二級(jí)和查詢緩存。如獲取到的為直接的結(jié)果集,則直接返 回,如獲取到的為一些ID的值,則再根據(jù)ID獲取相應(yīng)的值(Session.load()),最后形成結(jié)果集返回。可以看到,在這樣的情況下,list ()方法也是有可能造成N次查詢的。
查詢緩存在數(shù)據(jù)發(fā)生任何變化的情況下都會(huì)被自動(dòng)清空。
iterator()方法
Query的iterator()方法處理查詢的方式與list()方法是不同的,它首先會(huì)使用查詢語句得到ID值的列表,然后再使用Session的load()方法得到所需要的對(duì)象的值。
在獲取數(shù)據(jù)的時(shí)候,應(yīng)該依據(jù)這4種獲取數(shù)據(jù)方式的特點(diǎn)來選擇合適的方法。在開發(fā)中可以通過設(shè)置show_sql選項(xiàng)來輸出Hibernate所執(zhí)行的SQL語句,以此來了解Hibernate查詢方法是如何操作數(shù)據(jù)庫(kù)的。
【編輯推薦】