hibernate二级缓存问题

测试的时候看的出二级缓存是起作用的,但是在项目启动的时候,每次请求(相同的请求) 为什么都会发出sql语句,也就是说为什么每次request请求二级缓存都不起作用,难道request请求结束,二级缓存就失效了嘛?谁对二级缓存比较熟悉的,给小弟解答一下,谢谢

[code="java"]query.setCacheable(true);[/code]
我表示蛋疼+内伤
lz给我付药钱。

你说的发出SQL语句是发到数据库了吗

兄弟 是这样的。hibernate session(以下用session代指hibernate session)级别缓存是在每个session之内有缓存的,比如说你的每次request请求,一般都会独立生成一个session,那么当然是共享不到同一个session里面的。但是假如说你这次请求过后 马上又进入forward到另外一个action,那么此时共享的是一个session里面的数据,也就是说你的数据是用的刚才缓存起来的,为什么呢,因为我们知道forward相当于还是延续了前一个请求,就相当于共享了同一个session。

我曾经也研究过这类问题 下面的文章是我遇到过的问题 可以很好的说明问题
[url]
http://duyunfei.iteye.com/admin/blogs/993354
[/url]

楼上说的是一级缓存,即Session缓存。二级缓存是利用外部机制缓存,比如ehcache。
[quote]为什么都会发出sql语句[/quote]
每次发送sql,不一定命中数据库。
[quote]
the second level cache will only cache relations and entities you find [b]on id. Queries[/b] can't be cached by the second level cache and will always go to the database (or query cache).
[/quote]
[quote]
2nd level cache contains only entities by their ids, so when retrieving an entity by id (i.e. get, load or resolving a proxy implicitly) a 2nd level cache may be accessed. Any other queries (hal, criteria) will bypass the cache and hit the DB - at least as long as no query cache is used as well.
[/quote]
二级缓存只对根据实体的ID来缓存实体,所以只有在通过ID获取实体时才有可能访问二级缓存,比如,get,load方法。所有其他查询都会跳过缓存直接命中数据库,至少在没有使用查询缓存时是这样的。

那请问下myali88,hibernate怎么来设置2级缓存,能具体能说下么,我查询了好多资料都是轻描淡写说是用第三方插件...就是不知道怎么能在实际上项目中来使用和配置

兄弟 所有的问题 在这里不是hibernate 缓存的问题,而是你的缓存策略的问题。你的策略是每个请求都会生成一个hibernate session,保存在threadLocal种,即存在当前线程变量中。那么假如是同一个请求间的跳转,肯定会共享缓存,也就是不用发出sql。但是关键是你每次去请求,都是不同的请求,肯定不会公用缓存,因为每次不同请求,每次hibernate session都不同,肯定共享不了缓存,肯定得发出sql。

还有 lz说的缓存 其实应该说是 一级缓存。二级缓存对每次请求什么的都没什么关系的 ,那是数据库事务级别的缓存,即sessionFactory级别的。

所以你应该说的是hibernate session级别的缓存,即一级缓存。
有关概念问题,可以问我,我也写过这个方面的文档,供你参考。

二级缓存 基本上都不使用的。我们大部分用的项目 其实都在用的是session级别的一级缓存。

你所说的 查询缓存 其实基本上局限于同hibernate session里面的缓存。
真正的事务级别,不同数据库级别的sessionFactory,在hibernate其实支持的并不好。一般来说要么缓存功能强大,但事务级别弱,反之亦然。没有太好的支持。

我知道你说的意思 你的意思是配置二级缓存,为什么还是发sql。

我的意思是说你的二级缓存不是干这个事儿的,这个事儿是一级session缓存来干的,你配置的二级缓存当然不起到这个作用啦。

对啊,你只是看到Hibernate输出了SQL语句,并不是在数据库中看到了执行了SQL语句。
Hibernate只是输出日志而言,并不代表真的查询了数据库啊。。

我觉得redstarofsleep 也说的有道理 确实不一定执行了。你可以在执行以后查看数据库,看是否真的发送了sql到数据库。

[quote]
这个是我写的一个例子,在测试中二级缓存是起到作用的,而在项目中,每次请求都会发sql语句,就不知道为什么了
[/quote]
这个例子里的查询是以ID来的,所以会命中二级缓存。不知道你项目里的查询是怎么进行的。我上面说过了,二级缓存只对根据实体的ID来缓存实体。

大型的数据库分布式项目采用二级缓存,而二级缓存主要是用来在本数据库(同一个sessionFactory之内缓存数据的),对于请求域之内的缓存它其实不怎么管的,管不到那里去,而请求域之内的缓存我们一般都是用的一级缓存。
不过确实不排除lz配置的问题,二级缓存可以配置很多外部的缓存方式,每种策略都不大一样 得慢慢调。
而且二级缓存比较严格 出现命中的机会不大,而且生存期也有一些限制。

lz问题搞定了没有 可以继续讨论讨论啊 搞定了就分享一下啦。

第三方插件 去做 我们用c3p0较多些
http://www.iteye.com/topic/18904

还有 lz,你这个问题令我蛋疼和苦逼的一个很重要的方面是:你这个可以用一级缓存实现,真的。

是啊 你最初问的好像就是一个 request forward里的问题啊