select distinct item.reportoid, item.lineoid, item.accountoid, sun.amount, mon.amount, tue.amount, wes.amount, thur.amount, fri.amount, sat.amount
from expenseitem item
left join (select reportoid, accountoid, lineoid, amount, itemDate from expenseitem
where itemDate = '2007-11-04' ) sun
on item.reportoid = sun.reportoid and
item.accountoid = sun.accountoid and
item.lineoid = sun.lineoid and
item.itemDate = sun.itemDate
left join (select reportoid, accountoid, lineoid, amount, itemDate from expenseitem
where itemDate = adddate('2007-11-04', 1) ) mon
on item.reportoid = mon.reportoid and
item.accountoid = mon.accountoid and
item.lineoid = mon.lineoid and
item.itemDate = mon.itemDate
left join (select reportoid, accountoid, lineoid,amount, itemDate from expenseitem
where itemDate = adddate('2007-11-04', 2)) tue
on item.reportoid = tue.reportoid and
item.accountoid = tue.accountoid and
item.lineoid = tue.lineoid and
item.itemDate = tue.itemDate
left join (select reportoid, accountoid, lineoid,amount, itemDate from expenseitem
where itemDate = adddate('2007-11-04', 3) ) wes
on item.reportoid = wes.reportoid and
item.accountoid = wes.accountoid and
item.lineoid = wes.lineoid and
item.itemDate = wes.itemDate
left join (select reportoid, accountoid, lineoid,amount, itemDate from expenseitem
where itemDate = adddate('2007-11-04', 4) ) thur
on item.reportoid = thur.reportoid and
item.accountoid = thur.accountoid and
item.lineoid = thur.lineoid and
item.itemDate = thur.itemDate
left join (select reportoid, accountoid, lineoid,amount, itemDate from expenseitem
where itemDate = adddate('2007-11-04', 5) ) fri
on item.reportoid = fri.reportoid and
item.accountoid = fri.accountoid and
item.lineoid = fri.lineoid and
item.itemDate = fri.itemDate
left join (select reportoid, accountoid, lineoid,amount, itemDate from expenseitem
where itemDate = adddate('2007-11-04', 6) ) sat
on item.reportoid = sat.reportoid and
item.accountoid = sat.accountoid and
item.lineoid = sat.lineoid and
item.itemDate = sat.itemDate
where item.reportoid = 3712
order by reportoid, accountoid;
【IT168 技術(shù)文檔】很多人對二級緩存都不太了解,或者是有錯(cuò)誤的認(rèn)識,我一直想寫一篇文章介紹一下hibernate的二級緩存的,今天終于忍不住了。
我的經(jīng)驗(yàn)主要來自hibernate2.1版本,基本原理和3.0、3.1是一樣的,請?jiān)徫业念B固不化。
hibernate的session提供了一級緩存,每個(gè)session,對同一個(gè)id進(jìn)行兩次load,不會發(fā)送兩條sql給數(shù)據(jù)庫,但是session關(guān)閉的時(shí)候,一級緩存就失效了。
二級緩存是SessionFactory級別的全局緩存,它底下可以使用不同的緩存類庫,比如ehcache、oscache等,需要設(shè)置hibernate.cache.provider_class,我們這里用ehcache,在2.1中就是
hibernate.cache.provider_class=net.sf.hibernate.cache.EhCacheProvider
如果使用查詢緩存,加上
hibernate.cache.use_query_cache=true
緩存可以簡單的看成一個(gè)Map,通過key在緩存里面找value。
Class的緩存
對于一條記錄,也就是一個(gè)PO來說,是根據(jù)ID來找的,緩存的key就是ID,value是POJO。無論list,load還是
iterate,只要讀出一個(gè)對象,都會填充緩存。但是list不會使用緩存,而iterate會先取數(shù)據(jù)庫select
id出來,然后一個(gè)id一個(gè)id的load,如果在緩存里面有,就從緩存取,沒有的話就去數(shù)據(jù)庫load。假設(shè)是讀寫緩存,需要設(shè)置:
<cache usage="read-write"/>
如果你使用的二級緩存實(shí)現(xiàn)是ehcache的話,需要配置ehcache.xml
<cache
name="com.xxx.pojo.Foo" maxElementsInMemory="500" eternal="false"
timeToLiveSeconds="7200" timeToIdleSeconds="3600" overflowToDisk="true"
/>
其中eternal表示緩存是不是永遠(yuǎn)不超時(shí),timeToLiveSeconds是緩存中每個(gè)元素(這里也就是一個(gè)POJO)的超時(shí)時(shí)間,如果
eternal="false",超過指定的時(shí)間,這個(gè)元素就被移走了。timeToIdleSeconds是發(fā)呆時(shí)間,是可選的。當(dāng)往緩存里面put
的元素超過500個(gè)時(shí),如果overflowToDisk="true",就會把緩存中的部分?jǐn)?shù)據(jù)保存在硬盤上的臨時(shí)文件里面。
每個(gè)需要緩存的class都要這樣配置。如果你沒有配置,hibernate會在啟動的時(shí)候警告你,然后使用defaultCache的配置,這樣多個(gè)class會共享一個(gè)配置。
當(dāng)某個(gè)ID通過hibernate修改時(shí),hibernate會知道,于是移除緩存。
這樣大家可能會想,同樣的查詢條件,第一次先list,第二次再iterate,就可以使用到緩存了。實(shí)際上這是很難的,因?yàn)槟銦o法判斷什么時(shí)候是第一
次,而且每次查詢的條件通常是不一樣的,假如數(shù)據(jù)庫里面有100條記錄,id從1到100,第一次list的時(shí)候出了前50個(gè)id,第二次
iterate的時(shí)候卻查詢到30至70號id,那么30-50是從緩存里面取的,51到70是從數(shù)據(jù)庫取的,共發(fā)送1+20條sql。所以我一直認(rèn)為
iterate沒有什么用,總是會有1+N的問題。
(題外話:有說法說大型查詢用list會把整個(gè)結(jié)果集裝入內(nèi)存,很慢,而iterate只select
id比較好,但是大型查詢總是要分頁查的,誰也不會真的把整個(gè)結(jié)果集裝進(jìn)來,假如一頁20條的話,iterate共需要執(zhí)行21條語句,list雖然選擇
若干字段,比iterate第一條select
id語句慢一些,但只有一條語句,不裝入整個(gè)結(jié)果集hibernate還會根據(jù)數(shù)據(jù)庫方言做優(yōu)化,比如使用mysql的limit,整體看來應(yīng)該還是
list快。)
如果想要對list或者iterate查詢的結(jié)果緩存,就要用到查詢緩存了