我参考了一本关于java持久性和Hibernate的书。
(参见:https://www.manning.com/books/java-persistence-with-hibernate-second-edition)。
这本书反复提到" 状态快照" - 用于脏检查。
请参阅:
持久性上下文缓存永远不会自动收缩。保持 持久化上下文的大小到必要的最小值。经常,很多 您的上下文中的持久实例是偶然的 例如,因为您只需要几个项目,但查询了很多项目。 极大的图形会对性能产生严重影响 需要大量内存用于状态快照。检查一下你的 查询只返回您需要的数据,并考虑以下方法 控制Hibernate的缓存行为。
您可以调用EntityManager#detach(i)来驱逐持久化实例 从持久化上下文手动。你可以打电话 EntityManager#clear()分离所有持久化实体实例, 留给你一个空的持久化语境。
本机Session API有一些您可能会发现的额外操作 有用。您可以将整个持久性上下文设置为只读模式。 这会禁用状态快照和脏检查,而Hibernate则不会 写入对数据库的修改:
em.unwrap(Session.class).setDefaultReadOnly(true);
Item item = em.find(Item.class, ITEM_ID);
item.setName("New Name");
em.flush();
我的问题是:
Hibernate从@Entity
类创建的代理对象与上面提到的状态快照有什么区别?
我在哪里可以找到有关状态快照的更多文档?
编辑:考虑到纳罗斯的回答,我在会话类的hibernate文档中发现了非常有趣的信息:Session#setDefaultReadOnly
更改加载到此会话中的实体和代理的默认值 从可修改到只读模式,或从可修改到只读 模式。只读实体不进行脏检查和快照 不维持持久状态。只读实体可以 已修改,但更改不会保留。初始化代理时, 加载的实体将具有相同的只读/可修改设置 无论会话的当前情况如何,未初始化的代理都有 设置。更改特定的只读/可修改设置 已在此会话中的实体或代理
答案 0 :(得分:2)
不同之处在于他们所代表的。加载到持久性上下文中的任何对象几乎总是加载一些状态快照,无论它们可能是标识符还是只是非延迟加载的属性。
当实体加载到持久性上下文中时,实体的数据库列的值将存储在称为状态快照的对象数组中。它表示数据库级别的实体状态,我们可以在以后使用该状态,因为用户在事务的整个生命周期中更改实体对象的状态,例如进行脏检查。
另一方面,代理表示包装标识符的占位符。它确实维护了一些状态快照,通常是标识符,但它不是完整的数据库行,因此,也不能在代理实例上执行脏检查。