栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

concurrency in hibernate

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

concurrency in hibernate

您有两种方法来处理这种情况: 悲观主义者 锁定或 乐观主义者 锁定。但是您似乎都不使用两者,这可能解释了错误的行为。

  • 使用乐观锁定,Hibernate将检查在读取和保存用户帐户之间是否没有更改用户帐户。然后,并发事务可能会失败并回滚。

  • 使用悲观锁定,您可以在读取行时锁定该行,并且仅在事务完成时才将其解锁。这样可以防止并发事务读取会过时的数据。

刷新实体可能会读取新数据,也可能不会读取新数据,这取决于当前事务是否已经提交,但这也不是解决方案。由于似乎还创建了用户帐户(如果该帐户不存在),因此您不能如此轻松地应用悲观主义者锁定。我建议您然后使用乐观锁定(例如,使用时间戳来检测并发修改)。

阅读关于SO的另一个有关悲观主义者和乐观主义者锁定的问题。还可以查看hibernate章节“
事务和并发
”和“
hibernate注释 ”。


它应该是一样简单加入

@Version
上的相应字段中,
optimisticLockStrategy

默认值是
VERSION
(一个单独的列被使用)。

-更新-

您可以测试它是否可以在测试用例中使用。我创建了一个简单的实体

Counter
ID
value
以及
version
多个领域。

 public class Counter implements Serializable {    @Id    @GeneratedValue(strategy=GenerationType.AUTO)    @Basic(optional = false)    @Column(name = "ID")    private Integer id;    @Column(name = "VALUE")    private Integer value;    @Column(name = "VERSION")    @Version    private Integer version;    ...}

如果您 顺序 更新一个实体,它将起作用:

  id = insertEntity( ... );  em1.getTransaction().begin();      Counter c1 = em1.find( Counter.class, id );       c1.setValue( c1.getValue() + 1 );  em1.flush();  em1.getTransaction().commit();  em2.getTransaction().begin();  Counter c2 = em2.find( Counter.class, id );  c2.setValue( c2.getValue() + 1 );  em2.flush(); // OK  em2.getTransaction().commit();

我通过

value=2
和获得了一个实体
version=2

如果我模拟两个 并发 更新:

id = insertEntity( ... );em1.getTransaction().begin();em2.getTransaction().begin();Counter c1 = em1.find( Counter.class, id );Counter c2 = em2.find( Counter.class, id );c1.setValue( c1.getValue() + 1 );em1.flush();    em1.getTransaction().commit();c2.setValue( c2.getValue() + 1 );em2.flush(); // fail    em2.getTransaction().commit();

然后第二次冲洗失败:

Hibernate: update COUNTER set VALUE=?, VERSION=? where ID=? and VERSION=?Hibernate: update COUNTER set VALUE=?, VERSION=? where ID=? and VERSION=?Dec 23, 2009 11:08:46 AM org.hibernate.event.def.AbstractFlushingEventListener performExecutionsSEVERE: Could not synchronize database state with sessionorg.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [org.ewe.Counter#15]        at org.hibernate.persister.entity.AbstractEntityPersister.check(AbstractEntityPersister.java:1765)

之所以如此,是因为SQL语句中的实际参数是:

   update COUNTER set VALUE=1, VERSION=1 where ID=xxx and VERSION=0      --> 1 row updated   update COUNTER set VALUE=1, VERSION=1 where ID=xxx and VERSION=0      --> 0 row updated, because version has been changed in between


转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/394414.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号