Hibernate的save(transientInstance)引发的持久化对象三种状态思考
来源:互联网 发布:淘宝页面显示不全 编辑:程序博客网 时间:2024/05/23 19:51
一、 背景
今天同学在做spring+Hibernate的过程中出现一个问题:
12-10-09 09:48:46 | ERROR | org.hibernate.jdbc.BatchingBatcher 61 | Exception executing batch:
org.hibernate.StaleStateException: Batch update returned unexpected row count from update: 0 actual row count: 0 expected: 1
查看控制台输出异常栈定位了错误是在DAO中执行getHibernateTemplate().save(transientInstance);出错,而调用此操作的逻辑如下:
1. 查询满足条件的属性的List
getHibernateTemplate().find(queryString, cataID);
2. 逐个修改List中元组的部分属性内容
3. 删除原List对应的持久化对象
getHibernateTemplate().delete()
4. 将修改属性后的List对象逐个持久化保存到数据库中
getHibernateTemplate().save()
二、错误解决过程
1. google了一下发现很多人有同样的问题,即
1> 使用的是hibernate的saveOrUpdate方法保存实例(save方法其实底层也是用saveOrUpdate实现)。saveOrUpdate方法要求ID为null时才执行SAVE,在其它情况下执行UPDATE。在保存实例的时候是新增,但你的ID不为null,所以使用的是UPDATE,但是数据库里没有主键相关的值,所以出现异常。
这种问题的解决方法如下:
a. 修改主键增长策略increment(参考:google大部分博客里面都有)
b. 使用unsaved-value=null,避免在id不为null时定向到undate操作,而执行save操作(参考资料 )
2> 尝试了上面的解决方案后,问题依旧。我把执行逻辑进行了拆解,将delete和save分成两个函数,每个部分都执行find操作获取List,结果发现错误消失了,删除操作也执行成功了,但save操作未执行(showsql时,未生成insert语句)。这就意味着问题不是出在主键增长策略上,经查发现之前那个问题出在对Hibernate的可持久化对象三种状态不熟悉且未能与Hibernate的各种操作的对象要求结合起来(三态见链接),find获取的对象属于游离态,经过delete后在数据库中删除,接着执行save的对象还是游离态,两个操作的对象是同一个,所以会出现StaleStateException问题,而经过拆解后未操作相同的对象后,因为save持久化对象可临时态,而当前为游离态故无法持久化保存(未生成对应的sql)。类似问题见链接;
3> 最终解决办法是new一个对象(该对象为临时态),然后将处于游离态的对象内容copy给新new的对象,然后将new的对象save,问题解决!!
三、几点收获
1. 实践驱动、问题驱动学习确实比单看书要强N倍;
2. 纠错前先思考
3. 程序中bug无处不在,场景一遍问题会出很多,要有思想准备。
4. Hibernate中可持久对象三种状态的转换(使用场景)的理解很重要!!
- Hibernate的save(transientInstance)引发的持久化对象三种状态思考
- 【hibernate进阶】hibernate持久化对象的三种状态
- hibernate的持久化对象的三种状态
- Hibernate持久化对象的三种状态
- Hibernate持久化对象的三种状态
- Hibernate持久化对象的三种状态
- Hibernate持久化对象的三种状态
- Hibernate持久化对象的三种状态 .
- Hibernate持久化对象的三种状态
- Hibernate之持久化对象的三种状态
- Hibernate持久化对象的三种状态
- Hibernate持久化对象的三种状态
- hibernate持久化对象的三种状态
- Hibernate持久化对象的三种状态
- Hibernate持久化对象的三种状态
- 【SSH框架】--Hibernate持久化对象的三种状态
- 【Hibernate】——持久化对象的三种状态
- 【SSH系列】-- Hibernate持久化对象的三种状态
- 浅谈大型网站的算法和架构(1)
- 第13章 复制控制 (part2) 消息处理示例
- 爱是永久相思情
- 看到这张图,你有什么启发?
- vim插件
- Hibernate的save(transientInstance)引发的持久化对象三种状态思考
- typedef struct bit0 : 1
- 由于代码已经过优化或者本机框架位于调用堆栈之上,无法计算表达式的值”的解决方法
- 旧工程适配iOS 6和iPhone 5之第三方静态库
- 基于ARM-μCLinux嵌入式系统
- 工具分享:Dynamics CRM Job Editor
- C++中 explicit关键字
- 如何处理变大的EXCEL文件
- 内核链表中container_of实现