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

2022-09-02 12:40:27

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

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

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

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

还是完全不同的东西?


答案 1

Hibernate确实/可以使用字节码生成(CGLIB),这样一旦您调用设置器(甚至分配给字段afaict),它就会知道字段是脏的。

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

我说以上是基于最近对源代码(3.2.6GA)的拖网,无论增加什么可信度。兴趣点是:

  • SessionImpl.flush()触发事件。onFlush()
  • SessionImpl.list()触发事件的调用。(在感兴趣的表格上)。也就是说,查询可以调用刷新。有趣的是,如果没有事务,则不会发生刷新。autoFlushIfRequired()onAutoFlush()
  • 这两个事件最终都以 结束(以及其他有趣的位置) 在 。AbstractFlushingEventListener.flushEverythingToExecutions()flushEntities()
  • 这将循环访问会话 () 中的每个实体调用 。source.getPersistenceContext().getEntityEntries()DefaultFlushEntityEventListener.onFlushEntity()
  • 您最终会得到 。该方法确实对CGLIB脏标志进行了一些优化,但我们仍然最终循环遍历了每个实体。dirtyCheck()

答案 2

休眠会拍摄加载到会话中的每个对象的状态快照。刷新时,会话中的每个对象都与其相应的快照进行比较,以确定哪些对象是脏的。SQL 语句根据需要发出,并且快照将更新以反映(现在为干净的)会话对象的状态。


推荐