【问题标题】:Why hibernate flushes on select queries (EmptyInterceptor)?为什么休眠刷新选择查询(EmptyInterceptor)?
【发布时间】:2012-10-30 15:49:04
【问题描述】:

我想了解我看到的一种反直觉的休眠行为。我一直认为“刷新”意味着休眠在内存中有一个必须写入数据库的数据结构。这不是我所看到的。

我创建了以下拦截器:

public class FeedInterceptor extends EmptyInterceptor
{
    @Override
    public void postFlush(Iterator entities)
    {
          System.out.println("postFlush");          
    }
}

在我的 ApplicationContext 中注册它

<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
   <property name="entityInterceptor">
      <bean class="interceptor.FeedInterceptor"/>
   </property>
</bean>

但是,够奇怪的是,我看到从我的 DAO 从数据库中检索到的每一行都写入了“postFlush”:

Session session = sessionFactory.getCurrentSession();
Query query = session.createQuery("from Feed feed");
query.list();

为什么会这样?

【问题讨论】:

    标签: spring hibernate readonly interceptor flush


    【解决方案1】:

    假设 Hibernate 不会刷新会话,那么您可能会遇到以下情况:

    Person p = new Person();
    p.setName("Pomario");
    dao.create(p);
    Person pomario = dao.findPersonByName("Pomario")
    //pomario is null?
    

    当按姓名查找人员时,hibernate 会向数据库发出一条 select 语句。如果它没有先发送之前的语句,那么返回的结果可能与之前在会话中所做的更改不一致,这里dababase还没有收到create语句,所以它返回一个空的结果集。

    【讨论】:

    • 我希望刚刚创建的 Person 存在于某种形式的缓存(第一/第二级)中,并且休眠会很聪明地知道必须在 findPersonByName() 之前刷新脏数据针对数据库执行 - 与 findPersonByName() 的每一次调用相反,我在 query.list() 中看到了这种调用。请对此发表评论吗?
    • 你是对的,它可以检测到一些未保存的更改必须刷新到数据库,然后仅在需要时刷新休眠会话。我不明白你的问题。知道刷新是在 select 语句发出之前还是之后发生(例如,您可以设置 show_sql 参数)会很有趣。如果您在语句之后看到“postFlush”出现在控制台中,那么这可能意味着“flush”操作包括向数据库发出所有待处理的语句,最后一个是运行query.list()时需要执行的选择语句
    • 已经有这个优化了。如果你持久化或修改一个 Person,并执行一个只使用 Foo 实体的查询,Hibernate 不会在执行查询之前刷新。
    猜你喜欢
    • 1970-01-01
    • 2012-12-23
    • 1970-01-01
    • 2018-12-04
    • 1970-01-01
    • 2011-08-20
    • 1970-01-01
    • 2015-06-08
    • 1970-01-01
    相关资源
    最近更新 更多