Hibernate 1st和2nd Level缓存如何与多个会话一起使用

时间:2014-07-11 09:25:15

标签: java hibernate session caching transactions

我是Hibernate的新手,我知道level1缓存是会话范围,而level2缓存是跨会话,假设我有一个包含字段Id和Name的实体Person。

  1. 创建session1并加载一个人,Id = 1,Name =" AAA"

  2. 创建session2,更新此人,
    session.saveOrUpdate(person),Id = 1,Name =" BBB"

  3. 返回session1并再次更新, session.saveOrUpdate(person),Id = 1,Name =" AAA"


  4. 以下是我对hibernate内部工作的猜测:

    步骤1的

    hibernate搜索session1的level1缓存,没有任何内容

    hibernate搜索level2缓存,没有任何内容

    hibernate搜索数据库

    实体存储在level1和leve2缓存中

    现在,level1和level2缓存都有一个实体,id = 1且name =" AAA"


    第2步

    hibernate搜索session2的level1缓存,没有任何内容

    hibernate search level2 cache,获取实体(id = 1且name =" AAA")

    将此实体存储到session2的level1缓存中

    将此实体与session.saveOrUpdate(person)的参数进行比较

    名称已更改,因此需要进行更新

    session2的level1缓存已更新

    level2缓存已更新

    数据库已更新


    第3步

    hibernate搜索session1的level1缓存,获取实体(id = 1且name =" AAA")

    将此实体与session.saveOrUpdate(person)的参数进行比较

    没有改变

    所以数据库不会更新?


    我会尝试编写一些测试代码,但在此之前,如果有人可以指出上面的任何误解,我将非常感激,这将有助于我更深入地理解hibernate缓存。

    提前致谢。

1 个答案:

答案 0 :(得分:1)

除了以下几点之外,您的大部分假设都是正确的:

  • saveOrUpdate 不用于传播更新更改,而是用于:

    1. 坚持暂时实体(例如保存)
    2. 重新附加一个分离的实体(例如更新)

在Session中加载实体时,它会加载到第一级缓存中,并且在刷新时间内将发现并传播对实体所做的任何更改。因此,在这种情况下,您不必调用saveOrUpdate。

  • 在步骤3的示例中,Hibernate没有检测到第一个会话中的任何更改,因此即使其他会话已经更新了实体,也无需更新。

    为了防止"丢失更新" Hibernates提供:

    1. 乐观锁定(@Version)
    2. 悲观锁定(指示数据库获取锁)

如果您选择乐观锁定,并在步骤3中将实体名称更改为' CCC'你会得到一个org.hibernate.StaleObjectStateException(在刷新时),表明你有一个试图保存的实体的陈旧版本。