7

org.springframework.orm.ObjectOptimisticLockingFailureException错误查找及解决

 4 years ago
source link: https://www.wencst.com/archives/480
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

org.springframework.orm.ObjectOptimisticLockingFailureException错误查找及解决

作者: wencst 分类: JAVA,Uncategorized,数据库,程序设计 发布时间: 2017-03-08 17:16 阅读: 6,267 次

目前我们遇到了一个报错信息如下所示:

org.springframework.orm.ObjectOptimisticLockingFailureException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1; nested exception is org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1
    at org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:290) ~[spring-orm-4.1.0.RELEASE.jar:4.1.0.RELEASE]
    at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:214) ~[spring-orm-4.1.0.RELEASE.jar:4.1.0.RELEASE]
    at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:519) ~[spring-orm-4.1.0.RELEASE.jar:4.1.0.RELEASE]
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:757) ~[spring-tx-4.1.0.RELEASE.jar:4.1.0.RELEASE]
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:726) ~[spring-tx-4.1.0.RELEASE.jar:4.1.0.RELEASE]
    at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:496) ~[spring-tx-4.1.0.RELEASE.jar:4.1.0.RELEASE]
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:276) ~[spring-tx-4.1.0.RELEASE.jar:4.1.0.RELEASE]
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:95) ~[spring-tx-4.1.0.RELEASE.jar:4.1.0.RELEASE]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.1.0.RELEASE.jar:4.1.0.RELEASE]
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207) ~[spring-aop-4.1.0.RELEASE.jar:4.1.0.RELEASE]
    at com.sun.proxy.$Proxy236.deleteBalancer(Unknown Source) ~[na:na]

一开始,我是拒绝的……
这也能报错,只是个删除的操作,而且不能重现,完全不可理喻,是什么原因呢?
网上(某度)查了一些解决办法,大体归为几类:
1.操作本身问题,例如有设置了自增字段,而又对此表更新时设置了字段值;(这个当然pass掉,因为根本不是更新)
2.使用的是hibernate的saveOrUpdate方法保存实例。saveOrUpdate方法要求ID为null时才执行SAVE,在其它情况下执行UPDATE。在保存实例的时候是新增,但你的ID不为null,所以使用的是UPDATE,但是数据库里没有主键相关的值,所以出现异常;(这个也pass掉,因为不是SaveOrUpdate方法)
3. 在Hibernate映射一对多,多对一,多对多的时候新增常常会出现这个异常。(这个也pass,也不是新增)

各种解释都有,后来找了几个大牛问了一下,大体如下:
1.乐观锁异常,数据库并发导致
2.其他存储过程或者方法锁表,长期没有释放锁,导致报错
3.更新的字段有多个值
第三个解释应该不会,如果存在多个值,那这个记录应该永远都无法删除。
第二个解释和第一个解释,似乎也不太可能,因为翻了一下服务器的日志,没有找到操作这条记录相关的报错信息。

但第一个和第二个解释相对靠谱,于是朝着这个思路往下找。
发现如下现象:

1处为创建
2处为查询
3处为删除
4处删除报错
可以发现时间非常短,而另外有quartz服务器每5秒钟执行一次同步任务。
那么问题就出现了,3处删除时正好是quartz执行任务的时候,二者出现了并发。

即在2处与3处中间时,quartz已经将数据删除了,导致3处再删除时报错。
而日志中没有体现报错的原因是,quartz在删除时根本没有错误,所以一直未发现错误。
至此解决方法就很多了,保证数据一致性即可。

如果文章对您有用,扫一下支付宝的红包,不胜感激!

欢迎加入QQ群进行技术交流:656897351(各种技术、招聘、兼职、培训欢迎加入)


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK