问题
SSH框架下,spring的事务中提交时hibernate的sql执行顺序错乱,未按代码顺序实现。 JPA也是。
Hibernate在最终执行SQL语句时,居然是按INSERT, UPDATE, DELETE的顺序执行的,而非按照代码顺序执行!
代码中的执行顺序
事务提交后Hibernate Session中的执行顺序
原因
Hibernate为了性能优化,对象操作都是放在缓存里而没有立即执行数据库操作直到commit操作,为的是利用batch操作提高数据库操作性能。看完这句话感觉Hibernate还挺好,自行优化,如果只到这里那岂不是皆大欢喜。但是、但是、但是,Hibernate有个骚操作:在最终执行SQL语句时,会重新给SQL排序,按INSERT, UPDATE, DELETE的顺序执行的,而非按照代码顺序执行!W T F!L Z的业务逻辑怎么办?同理,在一个事务中混用Hibernate和Jdbc操作,也会导致数据不一致的问题。
具体的执行顺序:
所有对实体进行插入的语句,其顺序按照对象执行Session.save()的时间顺序
所有对实体进行更新的语句
所有进行集合删除的语句
所有对集合元素进行删除,更新或者插入的语句
所有进行集合插入的语句
所有对实体进行删除的语句,其顺序按照对象执行Session.delete()的时间顺序
解决办法
在需要同步的地方(即按照INSERT, UPDATE, DELETE顺序有可能产生问题的时候;混用JDBC操作的时候),执行session.flush()方案,该方法将缓存中的数据请求立即转换为数据库操作并执行
flush就是把sql缓冲区的sql语句发送到数据库去。
在大批量数据处理的时候,可能需要分批刷出数据,然后清空缓存,以减少内存占用量。
如果操作逻辑少的话,执行完每条sql都会返回一个int值(成功行数),>0则执行下一条sql,这样做,hibernate也会去判断,然后执行与代码一样逻辑的顺序。
参考博客:hibernate/jpa事务提交执行sql顺序(坑)
END 2020年4月19日21:55:52