Hibernate查询返回过时数据

时间:2015-05-20 14:50:49

标签: java hibernate caching

我有一个只从数据库中读取数据的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缓存,但仍无效...

有没有其他方法可以获取数据库中的更改?我是否在如何禁用缓存方面做错了什么?感谢。

更新 我通过监视数据库查询日志做了另一个实验:

  1. 第一次运行代码。检查日志。查询显示。
  2. 等几分钟。另一个应用程序更改了数据。我通过My​​Sql Workbench验证了它。为了区别于先前的查询,我添加了一个虚拟条件。
  3. 第二次运行代码。检查日志并显示查询。
  4. 这两次我都使用相同的查询,但由于数据已经改变,结果应该是不同的但不知道它不是......

4 个答案:

答案 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 之前,我遇到了相同的问题,其中返回了陈旧的数据。