开发反馈现场保存数据保存,是一个修改。错误信息为:EntityManager - 更新实体时出现异常! <org.springframework.orm.hibernate3.HibernateOptimisticLockingFailureException: Object of class [com.comtop.lcam.material.reqplan.requirement.model.RequirementItemVO] with identifier [07050000143601620150918000]: optimistic locking failed; nested exception is org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect):
这个错误是本质是:即将保存的数据比数据库的数据版本低,所以报错,是保证数据不会丢失更新。要解决这个问题的方向是,找到应用中的数据为什么跟数据库中的数据版本不一致,是版本数据传丢失了,还是数据库中的版本字段为null。
如果现在不知道什么是丢失更新,再举个例子:有一个场景修改人员的信息
8:00 用户1来到张三基本信息编辑页面,此时从数据库取了部分信息到系统页面,张三,28,13480904560,男,深圳福田
8:00 用户2来到张三基本信息编辑页面,此时从数据库取了部分信息到系统页面,张三,28,13480904560,男,深圳福田
8:01 用户1保存成功,保存内容为,张三,28,13480904560,男,深圳南山
8:08 用户2保存成功,保存内容为,张三,30,13480904560,男,深圳福田
用户2的数据不是吧用户1的数据覆盖了。到这里你可能会说,每次我只保存页面修改的数据不就可以解决这个问题吗?那你怎么样判断页面上的数据是否修改了,是不是要在页面上每个字段上加事件呢?低效又复杂,如果你做过前段,你就会认为不可行。
有解决方案,就是乐观锁,简单点说就是为每个数据加一个版本号,每修改一次自增,每次保存的时候与数据库的版本做比对,如果低于数据库版本就告诉用户,您的数据不是最新的。
最后查到是保存报错的表中version字段变为null了,而通过系统传过来的version是0。null和0不是一个东西。问了一下,最近这个表重建过,以前的表的version字段有一个check default 0,用create table的方式后这个check丢失了。来做个实验:
create table t(a number default 0);
create table t1 as select * from t;
create table T1
(
A number
);
可以看到T1果然丢失check。