hibernate如何处理冲突?

时间:2012-09-25 15:18:16

标签: java hibernate

我希望有人能为我澄清下面的场景。

据我所知,当你从hibernate请求'row'时,例如:

User user = UserDao.get(1);

我知道内存中有id = 1的用户。

在Web应用程序中,如果2个网页同时请求并加载用户,然后更新用户对象的属性,会发生什么? e.g:

user.pageViews += 1; // the value is current 10 before the increment
UserDao.update(user);

这会使用内存中的值(两个请求的值都是10),还是会使用数据库中的值?

2 个答案:

答案 0 :(得分:2)

您必须为两个用户使用两个休眠会话。这意味着内存中有两个对象实例。如果你只使用一个休眠会话(以及内存中对象的一个​​实例),那么结果是不可预测的。

在并发更新的情况下,第二次更新获胜。第二次更新将覆盖第一次更新的值。为了避免丢失第一次更新,您通常使用版本列(请参阅hibernate doc),然后第二次更新会收到一个错误,您可以捕获并对其做出反应(例如,出现错误消息“您的记录已被修改同时。请重新加载。“这允许第二个用户在修改后的记录上重做他的修改,以确保他的修改不会丢失。

对于页面视图计数器,就像在您的示例中一样,作为不同的解决方案,您可以编写一个同步方法,按顺序计算页面视图。

答案 1 :(得分:1)

默认情况下,in memory值用于更新。

在下文中,我假设您要实现自动页面查看计数器,而不是修改Web用户界面中的User。如果你想要这个,请看看 Hibernate乐观锁定

因此,假设您在计算网页浏览量时需要100%的准确性,您可以在修改其User值时锁定pageView实体,以获得表格行的排他性:

Session session = ...
Transaction tx = ...

session.lock(user, LockMode.UPGRADE);
user.increasePageViews();

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

LockMode.UPGRADE将在数据库的SELECT ... FOR UPDATE中进行转换,因此请小心保持锁定,以免影响应用程序的可伸缩性。