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 技术文档】很多人对二级缓存都不太了解,或者是有错误的认识,我一直想写一篇文章介绍一下hibernate的二级缓存的,今天终于忍不住了。
我的经验主要来自hibernate2.1版本,基本原理和3.0、3.1是一样的,请原谅我的顽固不化。
hibernate的session提供了一级缓存,每个session,对同一个id进行两次load,不会发送两条sql给数据库,但是session关闭的时候,一级缓存就失效了。
二级缓存是SessionFactory级别的全局缓存,它底下可以使用不同的缓存类库,比如ehcache、oscache等,需要设置hibernate.cache.provider_class,我们这里用ehcache,在2.1中就是
hibernate.cache.provider_class=net.sf.hibernate.cache.EhCacheProvider
如果使用查询缓存,加上
hibernate.cache.use_query_cache=true
缓存可以简单的看成一个Map,通过key在缓存里面找value。
Class的缓存
对于一条记录,也就是一个PO来说,是根据ID来找的,缓存的key就是ID,value是POJO。无论list,load还是
iterate,只要读出一个对象,都会填充缓存。但是list不会使用缓存,而iterate会先取数据库select
id出来,然后一个id一个id的load,如果在缓存里面有,就从缓存取,没有的话就去数据库load。假设是读写缓存,需要设置:
<cache usage="read-write"/>
如果你使用的二级缓存实现是ehcache的话,需要配置ehcache.xml
<cache
name="com.xxx.pojo.Foo" maxElementsInMemory="500" eternal="false"
timeToLiveSeconds="7200" timeToIdleSeconds="3600" overflowToDisk="true"
/>
其中eternal表示缓存是不是永远不超时,timeToLiveSeconds是缓存中每个元素(这里也就是一个POJO)的超时时间,如果
eternal="false",超过指定的时间,这个元素就被移走了。timeToIdleSeconds是发呆时间,是可选的。当往缓存里面put
的元素超过500个时,如果overflowToDisk="true",就会把缓存中的部分数据保存在硬盘上的临时文件里面。
每个需要缓存的class都要这样配置。如果你没有配置,hibernate会在启动的时候警告你,然后使用defaultCache的配置,这样多个class会共享一个配置。
当某个ID通过hibernate修改时,hibernate会知道,于是移除缓存。
这样大家可能会想,同样的查询条件,第一次先list,第二次再iterate,就可以使用到缓存了。实际上这是很难的,因为你无法判断什么时候是第一
次,而且每次查询的条件通常是不一样的,假如数据库里面有100条记录,id从1到100,第一次list的时候出了前50个id,第二次
iterate的时候却查询到30至70号id,那么30-50是从缓存里面取的,51到70是从数据库取的,共发送1+20条sql。所以我一直认为
iterate没有什么用,总是会有1+N的问题。
(题外话:有说法说大型查询用list会把整个结果集装入内存,很慢,而iterate只select
id比较好,但是大型查询总是要分页查的,谁也不会真的把整个结果集装进来,假如一页20条的话,iterate共需要执行21条语句,list虽然选择
若干字段,比iterate第一条select
id语句慢一些,但只有一条语句,不装入整个结果集hibernate还会根据数据库方言做优化,比如使用mysql的limit,整体看来应该还是
list快。)
如果想要对list或者iterate查询的结果缓存,就要用到查询缓存了