当我更新表时,我遇到一个奇怪的问题,当我尝试获取时,几秒钟后我仍然收到旧数据。当我再次使用相同的查询获取几秒后,我会收到刷新的数据。基本上我所看到的是返回新数据需要一些时间。
我已经禁用了所有来自hibernate的缓存,同时获取我正在将session.clear()和标记查询视为无法访问。
我也查看了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();
}
}
所以我正在清理会话,同样在我的配置中我已将所有缓存设置为禁用。当我更新记录时,如果我使用上述方法获取记录,那么我会在几秒钟内收到旧数据一次。之后它会给我最新的数据。
答案 0 :(得分:0)
如果在当前会话中加载了某些实体并且您运行了native query,则会话可能不会自动刷新。
Hibernate Session提供application-level repeatable reads,因此如果其他数据库事务更改实体,Hibernate将不会刷新当前实体状态。
现在,由于您没有发布UPDATE部分,因此很难说出您在那里做了什么。解决此问题的最佳方法是将所有JDBC语句记录为explained in this article。然后,您将确定是否已执行更新。
此外,您进行交易和会话管理的方式也存在缺陷。您甚至不在finally
块中回滚,并且由于您使用的是MySQL,因此可能会导致锁定并导致死锁。
只需使用Spring或Java EE等框架来为您处理持久性上下文和事务管理。
在你的例子中:
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
进行记录是错误的。使用Logging框架。FlushMode.MANUAL
或查询是本机SQL,而不是JPQL。查看this article for more details about the difference。rollback
?重点是什么?您不信任它正确发出UPDATE的数据库,现在您想要回滚该更改。或者,你怀疑Hibernate没有刷新,但是,如果没有发生变化,你为什么还要回滚呢,对吧?但如果它发生了,那么你应该阅读你的写作,因为这就是ACID isolation levels work。总而言之,您发布的代码中存在许多问题。因此,请阅读Hibernate用户指南和these tutorials,您将解决所有问题。别无他法。