我在理解HQL
查询从哪里获取信息时遇到了一些麻烦。我的项目使用不同的线程,每个线程读取/写入数据库。线程不共享会话对象,而是使用为我创建会话的HibernateUtil
类。
直到最近,我只会在写作后关闭会话,而不是在阅读后关闭会话。对对象的更改将立即在数据库中看到,但是当在其他线程(与用于写入的会话对象不同的会话对象(上读取时,我会得到过时的信息。读取和写入总是发生在不同的线程上,这意味着不同的会话对象和不同的会话缓存。
我一直认为通过使用HQL
而不是Criteria
,我将始终以数据库(或二级缓存(而不是会话缓存为目标,但在调试代码时,我清楚地知道 HQL 正在会话缓存中查找对象并检索到一个旧的过时对象。
我假设HQL
总是以数据库为目标是否错误?或者至少是二级缓存?
PS:我只使用一个SessionFactory
对象。
Hibernate有不同的缓存概念 - 实体缓存和查询缓存。实体缓存是会话缓存(以及第二级缓存,如果启用(的作用。
假设未启用查询缓存(默认情况下未启用(,则 HQL 将针对数据库执行。这将返回与查询匹配的实体的 ID。如果这些实体已经在会话缓存中,那么Hibernate将返回这些实体,而不是从数据库中重建它们。如果您的会话具有它们的过时副本(因为另一个会话已更新数据库(,那么这就是您遇到的问题。
我建议不要使用长寿命会话,主要是出于这个原因。应将会话的生存期限制为尝试执行的特定工作单元,然后将其关闭。 这样做对性能的影响很小或没有影响(假设您使用数据库连接池(。 或者,为了确保不会获得过时的实体,可以调用 Session.clear()
,但最终可能会产生意外的性能副作用。