一个 Hibernate 的事务问题
本文首发于 http://www.YoungZY.com/
工作中遇到一个问题。为了方便说明,做了简化。
业务要求:有两个接口,要么都成功,要么都失败。即任一个接口调用失败,两个接口相关的数据(如果库里有的话)都要删除。
假设:tab_two 中已有一条数据,再调接口时会报主键冲突。
期望的结果:第一次调用时失败,并把tab_two 中已有的一条数据清除。第二次调用成功。
问题:某一接口失败时,其数据未被清除。
伪码如上。写表Hibernate,删表JDBC。
接口2失败后,tab_one 的数据被清除了,但tab_two的数据还在。
猜测:Hibernate和JDBC有不同的事务处理机制。
以前也有类似的问题:
基于以上经验,修改代码:写表删表都用Hibernate。
经过测试,还是不行,失败接口的数据仍然存在。Debug的过程中发现,确实有delete,但删的是表里已有的数据,新数据(当前调用接口的数据)并未被删除,事务结束时被写入了表中。
想到Hibernate对象的三种状态:瞬时态(Transient)、持久态(Persistent)、脱管/游离态(Detached),于是使用了 evict(obj) 方法,结果还是不行。
通过日志发现,load之前会有insert,好像有个隐式的flush。
最后决定使用 getSession().clear()
试一下,居然意外地解决了。
没太搞清楚其中的原理,按照下图所示的各种状态之间的流转,evict和clear应该是一样的啊。
虽然不知其所以然,毕竟问题是解决了。
Hibernate版本:4.1.8.Final
版权声明: 本文为 InfoQ 作者【YoungZY】的原创文章。
原文链接:【http://xie.infoq.cn/article/47c7018caf674dbfa759fb1a2】。未经作者许可,禁止转载。
评论