Hibernate HQL只能访问会话缓存

ale*_*gen 7 database hibernate hql session-cache

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

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

我一直认为通过使用HQL而不是Criteria,我会始终瞄准数据库(或二级缓存)而不是会话缓存,但在调试我的代码时,我清楚地知道HQL正在寻找会话缓存中的对象并检索一个旧的过时的对象.

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

PS:我只使用一个SessionFactory物体.

ska*_*man 8

Hibernate有不同的缓存概念 - 实体缓存和查询缓存.实体缓存是会话缓存(以及第二级缓存,如果已启用)的功能.

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

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

  • @alegen:HQL将在每次*时针对数据库*运行,但是作为该查询的最终结果的Java对象可能来自会话缓存.这是默认行为. (4认同)