2

在以下代码示例中:

   Session session = getSessionFactory().openSession();

   MyObject currentState = (MyObject) 
           session.get(MyObject.class, id, new LockOptions(LockMode.???));

   if (!statusToUpdateTo.equals(currentState.getStatus())) {
     tx = session.beginTransaction();

     currentState.setStatus(statusToUpdateTo);
     session.save(currentState);

     tx.commit();
   }

   session.close();

正如您可能希望从代码中解释的那样,这个想法是检查我们的商店并找到具有给定 id 的对象,然后将其更新为给定状态。如果我们发现对象已经处于我们想要更新的状态,我们放弃做任何事情。否则,我们更新状态并将其保存回商店。

我担心的是,如果其中几个请求同时通过,并且都尝试读取和更新同一个对象怎么办?纵观文档,Hibernate 似乎“通常会自动获得完全正确的锁定级别”。(LockMode.class),但我仍然热衷于确保只有一件事可以读取对象,做出需要更新它的决定,然后更新它 - 没有任何其他线程对同一个数据库条目做同样的事情。

从 LockMode 类我认为PESSIMISTIC_WRITE 是我所追求的,但似乎无法找到证实这一点的文档资源。有没有人能够为我确认这一点,并且上面的代码会做我所追求的?

4

1 回答 1

4

因此,我注意到在我的原始代码中,会话关闭时,数据库上仍然保留了一个锁,因为当对它们调用 tx.commit() 时,删除我插入的行的后续调用没有完成。

添加以下 else 块后,我的测试通过了,我推断这意味着锁已被释放(因为现在正在清理这些行)。

   Session session = getSessionFactory().openSession();

   MyObject currentState = (MyObject) 
           session.get(MyObject.class, id, 
                       new LockOptions(LockMode.PESSIMISTIC_WRITE));

   if (!statusToUpdateTo.equals(currentState.getStatus())) {
     tx = session.beginTransaction();

     currentState.setStatus(statusToUpdateTo);
     session.save(currentState);

     tx.commit();
   } else {
     // Seems to clear lock
     tx = session.beginTransaction();
     tx.rollback();
   }

   session.close();

对我来说,这显然反映了我对 Hibernate 的锁定机制缺乏了解,但是使用 session.get(...) 或 session.load(...) 获得锁然后不释放锁似乎有点奇怪。使用会话本身锁定,但只能通过创建事务和提交/回滚来锁定。

当然,我可能只是误解了观察到的行为:)

于 2013-09-13T04:14:02.560 回答