【问题标题】:Hibernate first level cache - does it Sync?Hibernate 一级缓存 - 是否同步?
【发布时间】:2013-09-10 14:28:29
【问题描述】:

我知道@987654321@Hibernate 使用的第一级缓存,一旦我们从session 检索到一个实体,随后的get 调用对相同具有相同标识符的实体session而不是DB中获取,直到session打开

话虽如此,我对hibernate如何将一级缓存与DB同步有疑问?考虑以下场景

//Lets say I have created the session

Session s1 = sessionFactory.getSession();
User u1 = s1.get(User.class, 1); //Getting User with ID=1
//s1 is not yet closed

//Lets say I create some other session

Session s2 = sessionFactory.getSession();
User u2 = s2.get(User.class, 1); //Getting User with ID=1
u2.setName("Abc"); // Changed a field
s2.save(u2); // Saved the changes to DB
s2.close(); //Closed the 2nd session

//Now when I once again retrieve User with ID=1 from s1, will I get updated User?
User u3 = s1.get(User.class, 1);// Here as per my understanding cache is used

所以我的问题是

  • 既然u3 是从一级缓存中获取的,那么u3 是否有更新值?
  • 如果有人在会话打开时直接更新 DB 并修改 User 对象,session 是否与 DB 同步?

提前感谢您在此线程上花费的时间和精力

【问题讨论】:

    标签: java hibernate jpa hibernate-session


    【解决方案1】:

    不,Hibernate 不会将会话缓存中实体的状态与数据库同步,除非您明确请求。

    通常这不是问题,因为活动工作通常发生在事务内部,并且事务内部的操作不应该看到其他并发事务所做的更改(但细节取决于隔离级别)。因此,在这种情况下,Hibernate 的行为补充了事务隔离的典型语义。

    在某些情况下,实体的状态需要显式同步以反映在同一事务中所做的更改。它可能是由批量更新查询或执行数据库触发器引起的。在这种情况下,您需要通过调用 refresh() 来明确请求此类同步。

    【讨论】:

      【解决方案2】:

      您需要在s1 上调用Session.evict(Object),并使用u1 作为参数才能获得新的查找。或者,对于这种情况,您也可以在s1 上调用Session.clear() 以获得相同的效果。您也可以调用Session.refresh(Object object) 来刷新u1 的状态。

      请注意,事务在提交后可能需要一段不确定的时间(但通常不会很长)才能被其他客户端看到。使用不同连接的其他会话可能无法立即看到更新。

      【讨论】:

        【解决方案3】:

        一级(会话级)缓存确保加载的持久实例的状态 通过一个事务与其他事务所做的更改隔离。

        所以当您在第一个事务中调用s1.get(User.class, 1) 时,s2 在不同事务(T2) 中所做的更改是不可见的,因为这一次 Hibernate 将从会话级缓存 s1 中获取 User .

        【讨论】:

          猜你喜欢
          • 2022-08-15
          • 2017-02-20
          • 2014-06-28
          • 2013-10-31
          • 2013-12-14
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-02-05
          相关资源
          最近更新 更多