问题现象:
更新orders表中confirm_time字段,方法能成功返回,能查出修改后的数据,且无任何异常。但是方法调用结束后,数据库中confirm_time字段仍然为null值。
问题分析:
1,断点至543行, 即执行过537行的更新confirm_time操作后,如下图所示:
2,查看数据库中confirm_time; PS:这里要把数据库的事务隔离级别设置为 READ UNCOMMITTED ;即可以读到代码中未提交的事务的数据。 如下图:这个时候我们可以看到:confirm_time已经有值。
3,代码执行完成后,数据库confirm_time仍为空。那么数据为何没有保存成功呢?
分析可能原因:1,该代码中没有加入事务,导致数据没有提交入库。看了下代码,存在声明式的事务注解。排除该原因。
2,代码中出现了异常,导致事务回滚。整个断点调试的过程中并没有catch到任何异常,也排除。
3,数据更新后被其他更新操作覆盖了,好像是这个原因。分析如下:
在511行中,从数据库获取到ordersInfo;这个是数据库表映射对象。虽然537行成功更新了confirm_time;但是此时ordersInfo中的confirm_time仍为null;该类头上加了事物注解;
send方法结束后,ordersInfo被最终更新到数据库中,confirm_time此时被覆盖为空。
后续验证中添加ordersInfo.setConfirmTime(ShopHelper.getCurrentTimestam)后。confirm_time成功保存了。证明确实是这个原因。
附带hibernateLockMode(悲观锁和乐观锁)学习分享:
这里设置为UPGRADE_NOWAIT主要是避免在缓存中查询订单信息。保证查出来的订单信息是数据库中最新的。
锁定模式 | 描述 |
LockMode.NONE |
如果缓存中存在对象,直接返回该对象的引用,否则通过select语句到数据库中加载该对象,默认值. |
LockMode.READ |
不管缓存中是否存在对象,总是通过select语句到数据库中加载该对象,如果映射文件中设置了版本元素,就执行版本检查,比较缓存中的对象是否和数据库中对象版本一致 |
LockMode.UPGRADE |
不管缓存中是否存在对象,总是通过select语句到数据库中加载该对象,如果映射文件中设置了版本元素,就执行版本检查,比较缓存中的对象是否和数据库中对象的版本一致,如果数据库系统支持悲观锁(如Oracle/MySQL),就执行select...forupdate语句,如果不支持(如Sybase),执行普通select语句 |
LockMode.UPGRADE_NOWAIT |
和LockMode.UPGRADE具有同样功能,此外,对于Oracle等支持update nowait的数据库,执行select...for update nowait语句,nowait表明如果执行该select语句的事务不能立即获得悲观锁,那么不会等待其它事务释放锁,而是立刻抛出锁定异常 |
LockMode.WRITE |
保存对象时会自动使用这种锁定模式,仅供Hibernate内部使用,应用程序中不应该使用它 |
LockMode.FORCE |
强制更新数据库中对象的版本属性,从而表明当前事务已经更新了这个对象 |