介绍
持久性上下文使实体状态转换进入队列,该实体状态转换在刷新后转换为数据库语句。 对于托管实体,Hibernate可以代表我们自动检测传入的更改并安排SQL UPDATE。 这种机制称为自动脏检查 。
默认的脏检查策略
默认情况下,Hibernate检查所有托管实体属性。 每次加载实体时,Hibernate都会复制所有实体属性值。 在刷新时,每个受管实体属性都会与加载时快照值匹配:
因此,每个脏检查的数量由以下公式给出:
哪里
n =受管理实体的数量
p =给定实体的实体数
即使单个实体的仅一个属性发生了变化,Hibernate仍将检查所有托管实体。 对于大量的受管实体,默认的脏检查机制可能会占用大量CPU和内存。 由于初始实体快照是单独保存的,因此持久性上下文所需的内存是所有受管实体通常占用的内存的两倍。
字节码检测
一种更有效的方法是在值更改时标记脏属性。 与原始的深度比较策略类似,优良作法是将域模型结构与更改检测逻辑分离。 自动实体更改检测机制是一个跨领域的问题 ,可以在构建时或运行时进行编织。
实体类可以附加实现自动脏检查机制的字节码级指令。
编织方式
字节码增强可以发生在:
- 构建时间编译休眠实体之后,构建工具(例如ANT , Maven )将在每个已编译实体类中插入字节码级别的指令。 由于类是在构建时增强的,因此此过程不会产生额外的运行时损失。 可以针对增强的类版本进行测试,以便在构建项目之前验证实际的生产代码。
- 运行时可以使用以下方法完成运行时编织:
- Java代理,在实体类加载时进行字节码增强
迈向默认字节码增强脏检查
Hibernate 3一直通过ANT目标提供字节码检测,但是它从未成为主流,大多数Hibernate项目目前仍在使用默认的深度比较方法。
虽然其他JPA提供程序(例如OpenJPA , DataNucleus )一直在支持字节码增强方法,但是Hibernate才刚刚开始朝这个方向发展,提供了更好的构建时选项,甚至提供了自定义的脏检查回调 。
在我的下一篇文章中,我将向您展示如何使用自己的特定于应用程序的策略自定义脏检查机制。
翻译自: https://www.javacodegeeks.com/2014/08/the-anatomy-of-hibernate-dirty-checking.html