阅读更多
<转自http://fantasytree.iteye.com/blog/704953>
假设需要用乐观锁来实现一个物品数量增减操作的原子性,可以这样子做:(框架使用spring和hibernate)
Java代码
@Entity
@Table(name="tbl_gift")
public class Gift {
...
//乐观锁
@Version
private Long version;
...
}
Java代码
@Transactional(readOnly=false, propagation=Propagation.REQUIRED)
public void exchange(){
...
修改gift的剩余数量(采用乐观锁);
...
}
以上这段代码在并发修改下会有2种报错(org.hibernate.StaleObjectStateException)的可能:
(1)函数内(提交事务前);
线程1开事务->读礼品id=1,得version=0 -> 改剩余数量和version -> 提交事务
线程2开事务->读礼品id=1,得version=0 ----------------------------------->改剩余数量和version(出错)
(2)函数外(提交事务后);
线程1开事务->读礼品id=1,得version=0 -> 改剩余数量和version -> 提交事务
线程2开事务->读礼品id=1,得version=0 -> 改剩余数量和version ------------>提交事务(出错)
添加重试:
Java代码
@Transactional(readOnly=false, propagation=Propagation.REQUIRED)
public void exchange(){
...
修改gift的剩余数量(采用乐观锁);
...
}
public void exchange2() throws Exception {
try {
exchange();
} catch(org.hibernate.StaleObjectStateException e) {
exchange();
}
}
注意:是使用一个没有事务的方法包住一个有事务的方法。此外,如果在使用OpenSessionInView的情况下,这种重试的方法是没有作用的。