java - 重新附加分离的实例 : hibernate lock()

标签 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

In this case, it does matter whether changes are made before or after the object has been reattached. Changes made before the call to lock() aren’t propagated to the database, you use it only if you’re sure the detached instance hasn’t been modified. This method only guarantees that the object’s state changes from detached to persistent and that Hibernate will manage the persistent object again. Of course, any modifications you make to the object once it’s in managed persistent state require updating of the database. We discuss Hibernate lock modes in the next chapter. By specifying Lock- Mode.NONE here, you tell Hibernate not to perform a version check or obtain any database-level locks when reassociating the object with the Session. If you specified LockMode.READ, or LockMode.UPGRADE, Hibernate would execute a SELECT statement in order to perform a version check (and to lock the row(s) in the database for updating).

最佳答案

//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),您会看到传播的更改。

如果您注释锁定方法,则不会传播任何更改,因为第二个 session 不知道分离的项目。

关于java - 重新附加分离的实例 : hibernate lock(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27722274/

相关文章:

java - 在 java hibernate 中,父 id 不插入到具有一对多关系的子表

java - 在代理的activemq网络中禁用jmx(spring,xbean)

java - sessionFactory 没有被注入(inject)。它始终为空

mysql - JPA条件查询中的分组依据

java - hibernate getResultList() 返回不同的数据

java - 在 android 中访问 USB 大容量存储设备

java - 如何在 java 中处理基本身份验证

java - Hibernate 在设置父级后尝试两次保留子级

hibernate - 使用 transient 字段在 grails 中查询和排序数据库结果

java - 将注入(inject)的 EntityManager 传递给 Web session 持久对象