【问题标题】:Hibernate session cache behavior in clustered environment?集群环境中的休眠会话缓存行为?
【发布时间】:2018-07-10 16:51:01
【问题描述】:

在我参加的一次采访中,我被问到以下问题 -

假设我们有多集群的应用服务器,每个服务器都创建了自己的 SessionFactory(指向同一个数据库)。一台服务器检索记录 [Person with ID = 1],该记录在会话 (s1) 中缓存相同,该会话仍处于打开状态。

与此同时,另一台服务器打开另一个会话 (s2) 并更新 ID = 1 的人员记录。现在缓存在 s1 中的人员记录会发生什么情况?会不会是过时的记录?

我创建了一个小程序来模拟单个 JVM 上的场景。令我惊讶的是,尽管从同一个 SessionFactory 创建了 2 个会话,会话缓存仍保留了陈旧的数据。即使s1.flush() 也没有帮助。

    Session s1 = HibernateManager.getInstance().openNewSession();
    System.out.println("Opened session s1");
    Person p1 = s1.get(Person.class, 1);
    System.out.println("Retreived person with ID = 1 using s1, Name is");
    System.out.println(p1.getName()); //prints Test1
    
    Session s2 = HibernateManager.getInstance().openNewSession();
    System.out.println("Opened session s2");
    Person p2 = s2.get(Person.class, 1);
    System.out.println("Retreived person with ID = 1 using s2, Name is");
    System.out.println(p2.getName()); //prints Test1
    p2.setName("Test2");
    Transaction tx = s2.beginTransaction();
    s2.saveOrUpdate(p2);
    tx.commit();
    HibernateManager.getInstance().close(s2);
    System.out.println("Changed name and updated - closed s2");     
    
    p1 = s1.get(Person.class, 1);
    System.out.println("Retreived person with ID = 1 using s1 AGAIN, Name is");
    System.out.println(p1.getName()); //prints Test1
    
    System.out.println("Flushed s1");
    s1.flush();
    
    p1 = s1.get(Person.class, 1);
    System.out.println("Retreived person with ID = 1 using s1 AGAIN, Name is");
    System.out.println(p1.getName()); //still prints Test1. I was expecting Test2 because I flushed s1 (synced the session with DB)
    
    HibernateManager.getInstance().close(s1);

我的问题是,如果使用另一个会话更新同一记录,session 是否会使缓存失效?

【问题讨论】:

    标签: java hibernate hibernate-session


    【解决方案1】:

    是的 p1 将是一个陈旧的记录。如果更新 p1,在会话 s1 的会话刷新或事务提交时,p1 将覆盖 p2 的更新。

    为了防止这种情况,您可以使用 Optimistic locking。指定版本号(java 源代码中的@Version)(或 last-updated-date,如果您有这样的列)并指示 hibernate 使用此列进行版本更新。在这种情况下,如果我们更新 p1,在 session flush hibernate 将在更新前执行一个 select,看到版本信息不匹配(有人进入,中间并更新了记录)并抛出 StaleObject 异常

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-05-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-02-15
      • 2021-02-18
      • 1970-01-01
      • 2013-06-22
      相关资源
      最近更新 更多