Hibernate的SQL执行顺序引发的血案

问题起源于代码中对某个对象的处理逻辑,当发现该对象的某些属性变化时,先将原数据删除,再插入一个新对象,由于使用了Spring+Hibernate的组合,很容易写出如下代码:

?
1
2
3
4
5
6
7
8
9
//从数据库中读取原数据
Role entity = hibernateTemplate.load(ID);
//将数据复制到新对象上
Role newEntity = new Role();
BeanCopier.copy(entity, newEntity);
//删除原数据
hibernateTemplate.delete(entity);
//保存新数据
hibernateTemplate.save(entity);
然而这段代码在执行时却失败了,程序抛出:DataIntegrityViolationException异常,日志显示如下错误:
?
1
2
SQL Error: 1062, SQLState: 23000
Duplicate entry 'demo' for key 'IDX_ROLE_NAME'
即数据插入数据库时失败了,原因是触发了唯一性约束。经反复核实,数据库中数据没有问题,不是其他数据导致的,从代码逻辑上讲,这段代码先删后插也没有任何问题,在一个事务当中也没有什么脏读的问题,  这就搞笑了,问题到底出在哪呢???
打开Hibernate的SQL输出,还原最真实的SQL语句,终于找到了答案,输入日志如下:
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
Hibernate:
     /* insert com.litt.cidp.system.po.Role
         */ insert
         into
             role
             (ROLE_NAME, STATUS, REMARK)
         values
             (?, ?, ?)
Hibernate:
     /* update
         com.litt.cidp.system.po.Role */ update
             role
         set
             ROLE_NAME=?,
             STATUS=?,
             REMARK=?
         where
             ROLE_ID=?
Hibernate:
     /* delete com.litt.cidp.system.po.Role */ delete
         from
             role
         where
             ROLE_ID=?

Hibernate在最终执行SQL语句时,居然是按INSERT, UPDATE, DELETE的顺序执行的,而非按照代码顺序执行!What the F!查阅了相关资料,说是Hibernate为了性能优化,对象操作都是放在缓存里而没有立即执行数据库操作直到commit操作,为的是利用batch操作提高数据库操作性能;老天,那业务逻辑怎么办?同理,在一个事务中混用Hibernate和JDBC操作,将导致数据不一致问题

解决方案:在需要同步的地方(即按照INSERT, UPDATE, DELETE顺序有可能产生问题的时候;混用JDBC操作的时候),执行session.flush()方案,该方法将缓存中的数据请求立即转换为数据库操作并执行。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值