我对Hibernate的理解是,当对象从DB加载时,它们被添加到Session中.在不同的点上,根据您的配置,会话被刷新.此时,修改后的对象将写入数据库.
Hibernate如何确定哪些对象是"脏的"并且需要编写?
Hibernate生成的代理是否拦截了对字段的赋值,并将对象添加到Session中的脏列表中?
或者Hibernate是否查看Session中的每个对象并将其与对象的原始状态进行比较?
还是完全不同的东西?
Hibernate可以/可以使用字节码生成(CGLIB),这样一旦你调用setter(甚至分配给字段afaict)它就知道字段是脏的.
这会立即将该字段/对象标记为脏,但不会减少在刷新期间需要进行脏检查的对象数.它所做的只是影响实施org.hibernate.engine.EntityEntry.requiresDirtyCheck()
.它仍然进行逐场比较以检查肮脏.
基于最近通过源代码(3.2.6GA)的拖网,我说上面的内容,无论增加了什么可信度.兴趣点是:
SessionImpl.flush()
触发onFlush()
事件.
SessionImpl.list()
autoFlushIfRequired()
触发onAutoFlush()
事件的调用.(在感兴趣的表格上).也就是说,查询可以调用刷新.有趣的是,如果没有交易,则不会发生冲洗.
这两个事件最终都会结束,最终AbstractFlushingEventListener.flushEverythingToExecutions()
(在其他有趣的地方)最终flushEntities()
.
这会遍历session(source.getPersistenceContext().getEntityEntries()
)调用中的每个实体DefaultFlushEntityEventListener.onFlushEntity()
.
你最终会结束dirtyCheck()
.该方法确实对CGLIB脏标志进行了一些优化,但我们仍然最终循环遍历每个实体.
Hibernate会获取加载到Session中的每个对象的状态的快照.在刷新时,会话中的每个对象与其对应的快照进行比较,以确定哪些对象是脏的.根据需要发出SQL语句,并更新快照以反映(现在干净的)Session对象的状态.