重新附加一个分离的实例:hibernate lock()

时间:2014-12-31 14:10:29

标签: java hibernate jpa transactions locking

我有点困惑。我不明白为什么在lock()/ buildLockRequest()之前所做的更改会传播到数据库。

在此示例中,我的初始价格已设置,不应更新到数据库。但是如果我将它打印出来,它实际上已经更新了。或者改变了一些事情?本书正在使用Hibernate 3,而我正在使用Hibernate v3.6.10。

Session session = HibernateUtil.getSessionFactory().openSession();
Transaction tx = session.beginTransaction();

Item item = (Item) session.get(Item.class, new Long(1));

tx.commit();
session.close();

Session sessionTwo = HibernateUtil.getSessionFactory().openSession();
Transaction tx2 = sessionTwo.beginTransaction();
// Changes made before the call to lock() aren’t propagated to the database
item.setInitialPrice(new BigDecimal(179));

// sessionTwo.lock(item, LockMode.NONE);
sessionTwo.buildLockRequest(LockOptions.NONE).lock(item);
item.setDescription("This playstation 3 is in a fine state");
GregorianCalendar gc = new GregorianCalendar();
gc.setLenient(false);
gc.set(2015, 0, 31, 9, 12, 34);

item.setEndDate(gc.getTime());

item = (Item) sessionTwo.get(Item.class, new Long(1));

tx2.commit();
sessionTwo.close();

logger.debug(item.toString()); // still changes are made to initialPrice property

来自Java Persistence With Hibernate

  

在这种情况下,无论是在对象之前还是之后进行更改,无关紧要   重新连接。在调用lock()之前所做的更改不会传播到   数据库,只有在您确定未分离的实例时才使用它   改性。此方法仅保证对象的状态发生变化   分离到持久性并且Hibernate将再次管理持久对象。   当然,对象在托管持久性中进行的任何修改   state需要更新数据库。   我们将在下一章讨论Hibernate锁模式。通过指定Lock-   Mode.NONE在这里,你告诉Hibernate不要执行版本检查或获取任何版本   将对象与Session重新关联时的数据库级锁定。如果你指定了   LockMode.READ或LockMode.UPGRADE,Hibernate会执行SELECT   语句以执行版本检查(并锁定数据库中的行)   更新)。

1 个答案:

答案 0 :(得分:1)

//Changes made before the call to lock() aren’t propagated to the database
item.setInitialPrice(new BigDecimal(179));

这是预期的行为,因为项目对象已分离,并且分离的对象不受automatic dirty checking的约束,因此在此特定状态下不会将更改传播到数据库。

重新连接后:

sessionTwo.buildLockRequest(LockOptions.NONE).lock(item);

脏检查将在冲洗时应用。当您重新附加实体时,Hibernate会发出一个SQL SELECT来获取最新的实体状态,该状态将在刷新时用于将其与内存中的对象数据进行比较。

这就是锁定后的原因(即使对于LockOptions.NONE),您会看到传播的更改。

如果您对lock方法发表评论,那么自第二个会话以来,不会传播任何更改 不知道分离的项目。