代码之家  ›  专栏  ›  技术社区  ›  tgdavies

当Hibernate刷新会话时,它如何决定会话中哪些对象是脏的?

  •  17
  • tgdavies  · 技术社区  · 17 年前

    我对Hibernate的理解是,当从数据库加载对象时,它们被添加到会话中。根据您的配置,在不同的点刷新会话。此时,修改后的对象将写入数据库。

    Hibernate如何决定哪些对象是“脏的”并且需要写入?

    Hibernate生成的代理是否会截获分配给字段的内容,并将对象添加到会话中的脏列表中?

    或者Hibernate查看会话中的每个对象并将其与对象的原始状态进行比较?

    或者完全不同的东西?

    5 回复  |  直到 17 年前
        1
  •  22
  •   Bhesh Gurung AlexR    13 年前

    Hibernate使用/可以使用字节码生成(cglib),这样当您调用setter(甚至分配给字段afait)时,它就知道字段是脏的。

    这会立即将该字段/对象标记为脏的,但不会减少在刷新期间需要进行脏检查的对象的数量。它所做的只是影响 org.hibernate.engine.EntityEntry.requiresDirtyCheck() . 它 仍然 逐字段比较以检查是否有脏污。

    我是基于最近对源代码(3.2.6ga)的搜索而得出的上述结论,不管它增加了什么可信度。关注点包括:

    • SessionImpl.flush() 触发一个 onFlush() 事件。
    • SessionImpl.list() 电话 autoFlushIfRequired() 会触发一个 onAutoFlush() 事件。(在感兴趣的桌子上)。也就是说,查询可以调用刷新。有趣的是,如果没有事务,则不会发生刷新。
    • 这两件事最终都以 AbstractFlushingEventListener.flushEverythingToExecutions() 最后(除了其他有趣的地点)在 flushEntities() .
    • 在会话中的每个实体上循环( source.getPersistenceContext().getEntityEntries() 呼叫 DefaultFlushEntityEventListener.onFlushEntity() .
    • 你最终会在 dirtyCheck() . 该方法确实对cglib脏标志进行了一些优化,但是我们仍然结束了对每个实体的循环。
        2
  •  5
  •   alasdairg    17 年前

    Hibernate获取加载到会话中的每个对象的状态快照。在刷新时,将会话中的每个对象与其对应的快照进行比较,以确定哪些对象是脏的。根据需要发出SQL语句,并更新快照以反映(现在已清除)会话对象的状态。

        3
  •  1
  •   Jeroen Wyseur    17 年前

    查看org.hibernate.event.def.defaultflushentityeventlistener.dirtycheck 会话中的每个元素都会转到该方法,通过与未接触的版本(一个来自缓存或一个来自数据库)进行比较来确定它是否脏。

        4
  •  1
  •   Vlad Mihalcea    8 年前

    Hibernate default dirty checking mechanism 将遍历当前附加的实体,并将所有属性与其初始加载时间值匹配。

    您可以在下图中更好地可视化此过程:

    Default automatic dirty checking

        5
  •  0
  •   Community Mohan Dere    9 年前

    这些答案是不完整的(充其量——我不是这里的专家)。如果您的会话中有一个hib-man实体,您对它什么都不做,您仍然可以在调用save()时得到一个更新。什么时候?当另一个会话在Load()和Save()之间更新该对象时。下面是我的例子: hibernate sets dirty flag (and issues update) even though client did not change value

    推荐文章