我是Hibernate的新手,我知道level1缓存是会话范围,而level2缓存是跨会话,假设我有一个包含字段Id和Name的实体Person。
创建session1并加载一个人,Id = 1,Name =" AAA"
创建session2,更新此人,
session.saveOrUpdate(person),Id = 1,Name =" BBB"
返回session1并再次更新, session.saveOrUpdate(person),Id = 1,Name =" AAA"
以下是我对hibernate内部工作的猜测:
步骤1的
hibernate搜索session1的level1缓存,没有任何内容
hibernate搜索level2缓存,没有任何内容
hibernate搜索数据库
实体存储在level1和leve2缓存中
现在,level1和level2缓存都有一个实体,id = 1且name =" AAA"
hibernate搜索session2的level1缓存,没有任何内容
hibernate search level2 cache,获取实体(id = 1且name =" AAA")
将此实体存储到session2的level1缓存中
将此实体与session.saveOrUpdate(person)的参数进行比较
名称已更改,因此需要进行更新
session2的level1缓存已更新
level2缓存已更新
数据库已更新
hibernate搜索session1的level1缓存,获取实体(id = 1且name =" AAA")
将此实体与session.saveOrUpdate(person)的参数进行比较
没有改变
所以数据库不会更新?
我会尝试编写一些测试代码,但在此之前,如果有人可以指出上面的任何误解,我将非常感激,这将有助于我更深入地理解hibernate缓存。
提前致谢。
答案 0 :(得分:1)
除了以下几点之外,您的大部分假设都是正确的:
saveOrUpdate 不用于传播更新更改,而是用于:
在Session中加载实体时,它会加载到第一级缓存中,并且在刷新时间内将发现并传播对实体所做的任何更改。因此,在这种情况下,您不必调用saveOrUpdate。
在步骤3的示例中,Hibernate没有检测到第一个会话中的任何更改,因此即使其他会话已经更新了实体,也无需更新。
为了防止"丢失更新" Hibernates提供:
如果您选择乐观锁定,并在步骤3中将实体名称更改为' CCC'你会得到一个org.hibernate.StaleObjectStateException(在刷新时),表明你有一个试图保存的实体的陈旧版本。