`
lijiejava
  • 浏览: 262438 次
  • 性别: Icon_minigender_1
  • 来自: 南通
社区版块
存档分类
最新评论

Hibernate 乐观锁 org.hibernate.StaleObjectStateException 异常

阅读更多
         Hibernate乐观锁大多是基于数据版本(version)记录机制实现的。所谓的数据版本,就是为数据增加一个版本标识,在基于数据库表的版本解决方案中,一般是通过为数据库表增加一个version字段来实现。
        
          读取数据时,将此版本号一同读出,之后更新时,对此版本号加1。此时,将提交数据的版本号与数据库表对应记录的当前版本信息进行对比,如果提交的数据版本号大于数据库表中的当前版本号,则予以更新,否则认为是过期数据。
        
         乐观锁 测试:

        User 类:
public class User implements Serializable{ 
	private int id; 
	private String name; 
	private int version;
    ...
}


       User.hbm.xml映射文件:
<hibernate-mapping>
	<class name="po.User" table="t_user" lazy="false" optimistic-lock="version">
		<id name="id">
			<generator class="native" />
		</id> 
		<version name="version" column="version" type="integer"/>
		<property name="name" />  
	</class>
</hibernate-mapping>


         测试代码:
  Session session = sessionFactory.openSession();
		Session session2 = sessionFactory.openSession();
		
		User user = (User)session.load(User.class, new Integer(1));
		User user2 = (User)session2.load(User.class, new Integer(1)); 

  Transaction tx = session.beginTransaction();  
		
		Transaction tx2 = session2.beginTransaction(); 
		user2.setName("AAA");
		tx2.commit();		
 		
		user.setName("BBB");
  tx.commit();


  运行以上代码,会抛出如下异常:
org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect) 


再次运行以上代码,不会抛出异常,会对数据库中记录进行更新。

原因:
在第一次测试之后,会将数据库表中id=1的记录的name属性值设为”AAA”(由于事务tx2先执行)。再次测试,由于Hibernate的缓存(在调用load方法时会将查询到的对象进行缓存),执行事务tx2时不会发出sql语句(因为更新后的值与加载到的值相同),也就意味着数据库表中对应记录的version值没有加1,所以事务tx可以提交成功。如果更新user的name属性,关键要考虑与load得到的对象相比是否有变化,是否需要发出sql语句,如果两个事务都要发出sql语句,就会冲突。Hibernate本身发出sql语句是没有错的,但在关键数据库中会发生冲突。
要注意的是:上述测试都是在“lazy=false”的条件下执行的,如果将“lazy=false”去掉,默认采用延迟加载,那么不会出现冲突问题,发出的sql语句如下:


Hibernate: select user0_.id as id0_0_, user0_.version as version0_0_, user0_.name as name0_0_ from t_user user0_ where user0_.id=?
Hibernate: update t_user set version=?, name=? where id=? and version=?

Hibernate: select user0_.id as id0_0_, user0_.version as version0_0_, user0_.name as name0_0_ from t_user user0_ where user0_.id=?
Hibernate: update t_user set version=?, name=? where id=? and version=?


即每次都是查询更新,因为load时采用延迟加载,得到的只是一个代理对象,当对user进行设置时,会发出sql语句查询,紧接着就是更新语句。所以两次select查询得到的version值不同,不会冲突。
分享到:
评论
5 楼 lijiejava 2010-08-03  
phenom 写道
有些使用Select  for update解决的.
照LZ的分析,必须使用延迟加载了?


我只是分析了一下原因,没有说必须使用延迟加载,for update是悲观锁机制吧???
4 楼 phenom 2010-08-03  
有些使用Select  for update解决的.
照LZ的分析,必须使用延迟加载了?
3 楼 gwpking8419 2010-08-03  
只有原因,没有总结吗
2 楼 pclfs1983 2010-08-02  
学习了 3q
1 楼 hatedance 2010-08-02  
谢谢lz的帖子,写的清晰明了。

相关推荐

    Hibernate乐观锁和悲观锁分析

    【Hibernate乐观锁与悲观锁详解】 在开发过程中,尤其是在并发环境下,确保数据的一致性和完整性至关重要。Hibernate,作为Java领域广泛使用的ORM框架,提供了一种处理并发数据访问冲突的手段,那就是锁机制。主要...

    Hibernate悲观锁和乐观锁的实现

    在Hibernate源码中,乐观锁的实现主要依赖于`AbstractEntityPersister`类的`checkOptimisticLocking()`方法,它会比较当前对象的版本信息与数据库中的版本信息,如果不同则抛出`StaleObjectStateException`异常。...

    Hibernate的乐观锁与悲观锁

    ### Hibernate的乐观锁与悲观锁 #### 一、引言 在并发环境下,尤其是在金融、电商等业务场景中,确保数据的一致性和完整性至关重要。**Hibernate**作为一种流行的Java持久层框架,提供了多种机制来处理并发控制...

    Hibernate version 乐观锁 (xml方式)

    在了解了Hibernate乐观锁的XML配置后,我们可以结合源码进一步分析其实现细节。在Hibernate中,乐观锁的处理主要在`org.hibernate.event.internal.DefaultMergeEventListener`和`org.hibernate.event.internal....

    乐观锁version-练习

    2. **Hibernate的乐观锁机制**:了解Hibernate如何通过`version`字段实现乐观锁,包括`@Version`注解的使用、对象状态管理及冲突检测。 3. **乐观锁与悲观锁的区别**:对比两种锁的优缺点,例如悲观锁的资源消耗大...

    Hibernate.lock()方法中各种锁的区别.docx

    在Hibernate中,可以通过版本号检查来实现乐观锁。在数据库中添加一个`VERSION`字段记录版本号,读取数据时一起读取版本号,在更新数据时递增版本号,并对比版本号。 **Hibernate实现**: 首先在实体类中增加版本号...

    Hibernate中,利用版本管理机制来控制事务并发

    1. 版本号原理:Hibernate使用乐观锁策略,即假定在正常情况下,同一时间只有一个用户修改数据,当多个用户同时修改时,通过比较版本号判断是否有冲突。每个被管理的对象都有一个版本属性,每次更新对象时,...

    hibernate错误汇总

    错误十:Exception in thread "main" org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect) 错误原因:这个异常通常发生在并发...

    Hibernate update问题

    在更新过程中可能会遇到各种异常,如`StaleObjectStateException`表示并发冲突,`OptimisticLockingFailureException`表示乐观锁失败,应适当地捕获和处理这些异常,确保应用的健壮性。 总之,理解Hibernate的更新...

    hibernate各种操作

    Hibernate的异常体系基于JDBC,如`HibernateException`、`StaleObjectStateException`等,需要合理捕获并处理。 14. 动态模型 Hibernate的`DynamicModel`允许在运行时动态创建实体,适用于不确定数据结构的场景。...

    一种基于hebernate乐观锁的信息系统开发模型 (2012年)

    标题中提到的“基于Hibernate乐观锁的信息系统开发模型”是一个工程技术领域的知识点,主要是关于信息系统开发方面的实践。Hibernate是一种流行的Java对象关系映射(ORM)框架,它用于将Java对象映射到数据库的表...

    Linq2NHibernate.Step1

    在实际应用中,应妥善处理可能出现的异常,如`StaleObjectStateException`(脏对象状态异常)和`OptimisticLockException`(乐观锁异常)。 通过上述步骤,你就可以在项目中使用LINQ to NHibernate进行数据操作了...

    NHibernate实例

    10. **异常处理**:在实际开发中,需要捕获并适当地处理可能出现的NHibernate和数据库相关的异常,例如`StaleObjectStateException`(脏对象状态异常)和`OptimisticLockingFailureException`(乐观锁失败异常)。...

    随机获取oracle数据库中的任意一行数据(rownum)示例介绍

    如果发生并发冲突,乐观锁会抛出异常,如`org.hibernate.StaleObjectStateException`,从而可以捕获异常并重新尝试获取奖品。 除了`ROWNUM`,Oracle还提供了其他有用的分析函数,如`RANK()`、`ROW_NUMBER()`和`LAG...

Global site tag (gtag.js) - Google Analytics