在以下代码示例中:
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的对象,然后将其更新为给定状态。如果我们发现对象已经处于我们想要更新的状态,我们就会放弃做任何事情。否则,我们会更新状态并将其保存回商店。
我担心的是,如果其中一些请求同时出现,并且所有请求都尝试读取和更新同一个对象,那该怎么办?透过doco看起来,Hibernate"通常会自动获得正确的锁定级别。" (LockMode.class)但我仍然热衷于确保只有一件事可以读取对象,做出更新它需要的决定,然后更新它 - 没有任何其他线程对同一个数据库做同样的事情条目。
从LockMode类我认为 PESSIMISTIC_WRITE就在我之后,但似乎无法找到证实这一点的文档资源。是否有人能够为我确认这一点,并且上述代码将执行我之后的操作?
答案 0 :(得分: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(...)获得锁定然后不使用会话本身释放锁,而是仅通过创建事务并提交/回滚。
当然,我可能只是误解了观察到的行为:)