7

我在理解HQL查询从哪里获取信息时遇到了一些麻烦。我的项目使用不同的线程,每个线程读取/写入数据库。线程不共享 Session 对象,而是使用一个HibernateUtil为我创建会话的类。

直到最近,我只会在写作后关闭会话,而不是在阅读后。对对象的更改将立即在数据库中看到,但是在其他线程上读取时(与用于写入的会话对象不同)我会得到陈旧的信息。读取和写入总是发生在不同的线程上,这意味着不同的会话对象和不同的会话缓存。

我一直认为通过使用HQL而不是Criteria,我将始终以数据库(或二级缓存)而不是会话缓存为目标,但是在调试我的代码时,我很清楚 HQL 正在会话缓存中寻找对象并检索了一个旧的过时对象。

假设HQL总是以数据库为目标,我错了吗?或者至少是二级缓存?

PS:我只使用一个SessionFactory对象。

4

1 回答 1

7

Hibernate 有不同的缓存概念——实体缓存和查询缓存。实体缓存是会话缓存(以及二级缓存,如果启用)所做的。

假设未启用查询缓存(默认情况下未启用),那么您的 HQL 将针对数据库执行。这将返回与查询匹配的实体的 ID。如果这些实体已经在会话缓存中,那么 Hibernate 会返回这些实体,而不是从数据库中重建它们。如果您的会话有它们的旧副本(因为另一个会话已经更新了数据库),那么这就是您遇到的问题。

我建议不要使用长期会话,主要是因为这个原因。您应该将会话的生命周期限制为您尝试执行的特定工作单元,然后将其关闭。这样做几乎没有或没有性能损失(假设您使用数据库连接池)。或者,为了确保您不会获得过时的实体,您可以调用Session.clear(),但您最终可能会遇到意想不到的性能副作用。

于 2012-05-10T11:34:08.767 回答