我希望有人能为我澄清下面的场景。
据我所知,当你从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),还是会使用数据库中的值?
答案 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
中进行转换,因此请小心保持锁定,以免影响应用程序的可伸缩性。