我在更新表时遇到了一个奇怪的问题,几秒钟后当我尝试获取它时我仍然收到旧数据。当我在几秒钟后再次使用相同的查询获取时,我会收到刷新的数据。基本上我看到的是返回新数据需要一些时间。
我在获取 session.clear() 并将查询标记为不可缓存时也禁用了 hibernate 中的所有缓存。
我还查看了 mysql 查询日志,发现 hibernate 正在查询 mysql,但我收到的是旧数据。
我怎样才能确保在任何给定的时间点我只收到刷新的数据
下面是我的 hibernate 配置文件
<hibernate-configuration>
<session-factory>
<property name="dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property>
<property name="show_sql">true</property>
<property name="connection.url">jdbc:mysql://127.0.0.1:4804/aluminidb?autoReconnect=true</property>
<property name="connection.username">root</property>
<property name="connection.password">root</property>
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<!-- Example mapping file inclusion -->
<property name="hibernate.cache.use_second_level_cache">false</property>
<property name="hibernate.cache.use_query_cache">false</property>
<!-- Disable the second-level cache -->
<property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>
<mapping resource="com/alumini/spring/model/Alumini.hbm.xml"/>
<mapping resource="com/alumini/spring/model/Question.hbm.xml"/>
<mapping resource="com/alumini/spring/model/Events.hbm.xml"/>
</session-factory>
下面是获取对象的代码
@Override
public Alumini login(String email, String password) {
Session session=sessionFactory.openSession();
session.clear();
Transaction t;
try{
t=session.beginTransaction();
Query query = session.getNamedQuery("chkLogIn");
query.setParameter("email",email);
query.setParameter("password",password);
query.setCacheMode(CacheMode.REFRESH);
query.setCacheable(false);
List<Alumini> aluminiList=query.list();
if(aluminiList!=null && aluminiList.size()>0){
System.out.println(aluminiList.get(0).getLastUpdated());
t.commit();
return aluminiList.get(0);
}else{
t.rollback();
return null;
}
}finally{
session.close();
}
}
所以我正在清除 session ,同样在我的配置中我已将所有缓存设置为禁用。仍然在我更新记录时,如果在几秒钟内使用上述方法获取记录,那么我会收到一次旧数据。之后它会给我最新的数据。
最佳答案
如果在当前 session 中加载了某些实体并且您运行了 native query , Session 可能不会自动刷新。
Hibernate Session 提供 application-level repeatable reads , 因此如果其他数据库事务更改了实体,Hibernate 将不会刷新当前实体状态。
现在,因为您没有发布 UPDATE 部分,所以很难说您在那里做了什么。解决此问题的最佳方法是简单地将所有 JDBC 语句记录为 explained in this article .然后,您将确定更新是否已执行。
此外,您进行事务和 session 管理的方式也存在缺陷。您甚至不会在 finally
block 中回滚,并且由于您使用的是 MySQL,这可能会导致锁定并导致死锁。
只需使用像 Spring 或 Java EE 这样的框架来为您处理 Persistence Context 和事务管理。
在你的例子中:
Session session=sessionFactory.openSession();
session.clear();
如何判断这是一个新的Session
,调用clear
没有任何意义,还是同一个Session
你用于更新?
根据这段代码,我假设是这种情况:
if(aluminiList!=null && aluminiList.size()>0){
System.out.println(aluminiList.get(0).getLastUpdated());
t.commit();
return aluminiList.get(0);
}else{
t.rollback();
return null;
}
但它指出您可能跳过了 Hibernate User Guide并开始编写 Hibernate。
aluminiList
永远不能为空。它只能是空的。- 通过
System.out
记录是错误的。为此使用日志记录框架。 - 为什么要在查询执行后提交?也许更改根本没有刷新并且查询没有触发刷新,因为您设置了
FlushMode.MANUAL
或者查询是 native SQL,而不是 JPQL。查看this article for more details about the difference . - 您在 else 上调用了
rollback
?重点是什么?您不信任它正确发出 UPDATE 的数据库,现在您想回滚该更改。或者,您怀疑 Hibernate 没有刷新,但是,如果没有发生更改,您为什么要回滚它,对吗?但如果它发生了,那么你应该读你写的,因为这就是ACID isolation levels work的方式。 .
总而言之,您发布的代码中存在很多问题。因此,请阅读 Hibernate 用户指南和 these tutorials ,您将解决所有问题。没有其他办法。
关于java - MySQL 或 Hibernate 缓存问题接收旧数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30918154/