我有一个只从数据库中读取数据的hibernate查询(hibernate 3)。数据库由单独的应用程序更新,查询结果不反映数据库中的更改。
通过一些研究,我认为它可能与Hibernate L2缓存有关(我不认为它是L1缓存,因为我总是打开一个新会话并在它之后关闭它#39;完成了。
$regex
我尝试在hibernate配置文件中禁用第二层缓存,但它无法正常工作:
MATCH (u:user { user_id:"1" })
MATCH (o:user)
WHERE o <> u
OPTIONAL MATCH (u)-[r:games_like]->(d)<-[rw:games_like]-(o)
RETURN
toInt(r.rating_val)+toInt(rw.rating_val) as sum ,
collect(DISTINCT (r.rating_val)) AS user1,
collect(DISTINCT (rw.rating_val)) AS user2,
d
ORDER BY sum DESC
我还在Session session = sessionFactoryWrapper.getSession();
List<FlowCount> result = session.createSQLQuery(flowCountSQL).list();
session.close();
之后添加了<property name="hibernate.cache.use_second_level_cache">false</property>
<property name="hibernate.cache.use_query_cache">false</property>
<propertyname="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>
来强制刷新L1缓存,但仍无效...
有没有其他方法可以获取数据库中的更改?我是否在如何禁用缓存方面做错了什么?感谢。
更新 我通过监视数据库查询日志做了另一个实验:
这两次我都使用相同的查询,但由于数据已经改变,结果应该是不同的但不知道它不是......
答案 0 :(得分:1)
为了强制执行L1缓存刷新,您可以使用Session的刷新(对象)方法。
来自Hibernate Docs,
从底层数据库重新读取给定实例的状态。 不建议使用它来实现长时间运行的会话 跨越许多业务任务。然而,该方法在某些方面是有用的 特殊的情况。例如
- 数据库触发器在插入或更新时更改对象状态
- 在同一会话中执行直接SQL(例如,批量更新)后
插入Blob或Clob后
此外,您提到您添加了session.setCacheMode(CacheMode.Refresh)
以强制刷新L1缓存。这不起作用,因为CacheMode不必对L1缓存做任何事情。再次来自Hibernate Docs,
CacheMode控制会话与第二级的交互方式 缓存和查询缓存。
答案 1 :(得分:0)
如果没有二级缓存和查询缓存,hibernate将始终在新会话中从数据库中获取所有数据。
如果要查看绑定变量,可以通过为org.hibernate
包启用DEBUG日志级别(以及org.hibernate.type
的TRACE级别)来检查Hibernate执行的查询。
答案 2 :(得分:0)
查询反映了多大的变化?如果它在某个时间后显示更改,则可能与您获取会话的方式有关。
我不熟悉SessionFactoryWrapper类,这是你编写的自定义类吗?你是否以某种方式缓存会话对象的时间超过了必要的时间?如果是,则查询将重新使用已在会话中加载的对象。这是Hibernate保证的可重复读取语义背后的理念。
您可以在运行查询之前清除会话,然后它将返回最新数据。
答案 3 :(得分:0)
Hibernate的内置连接池机制被窃听。
将其替换为 c3p0 等生产品质替代品。
在我开始使用 c3p0 之前,我遇到了相同的问题,其中返回了陈旧的数据。