导航菜单
路很长,又很短
博主信息
昵   称:Cocodroid ->关于我
Q     Q:2531075716
博文数:335
阅读量:1127966
访问量:114685
至今:
×
云标签 标签球>>
云标签 - Su的技术博客
博文->>首页 博主的更多博文>>
仅使用set属性值就把数据库数据给改了
Tags : springboot,jpa发表时间: 2020-04-09 20:39:51
原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否则将追究法律责任。
比如: 转自:Su的技术博客  原文地址:

1

背景

最近小伙伴要上线一个小特性——审阅状态的变更。在上线的过程中,发现一个非常奇怪的问题。


基本上保证了逻辑没问题 ,多次检查也没问题。但是事实就是发生了!

小伙伴有点怀疑人生了:)。


所以我们临时的处理方式是增加日志打印,逐步验证我们的逻辑。看看我们是如何排查问题的。


使用的技术框架:springboot+jpa



2

问题排查


1)原逻辑代码

ALog aLog = aLogRepository.findOne(logId); 
if (aLog.getStatus == UNKNOWN) {
    aLog.setStatus(INIT); // ① 
} else {
    // ②     
    aLog.setStatus(RUNNING);     
    aLogRepository.save(aLog);
    return;
} 
// ③发送短信 
smsAdapter.sendSms("手机号", "状态变更..."); return true; 


上面是经过抽离的主要逻辑,存在的问题


逻辑不会进入到②,只会进入到①和③,也就是当前的记录状态无需更新,并且需要发送短信。但是数据库的aLog记录状态就被更新了,到底是为什么?又没有调用save方法进行更新记录,怎么就会把数据给改了?


由于多次检查和增加日志逻辑验证,我们最终是确保逻辑是没问题的。


此时,我想到了唯一一个问题,就是跟Hibernate的对象状态有关!那么到底是不是呢,我们就得继续排查确认了。


2)原来是这样的

smsDao.save(sms); 
smsHandle.sendSms(); 



查看了发送短信的逻辑,原来这里会将短信记录保存到数据库,再调用短信接口发送对应的短信内容。


那么,很有可能就是这里的smsDao.save帮忙把aLog顺便一起update了?事实确实如此。小伙伴就把发送短信的逻辑代码注释掉,重新测试调用接口,这时aLog数据库记录就不会被更新了。


所以罪魁祸首就是“”。


这个时候就确定了是Hibernate包含了三种状态,此时aLog查询出来,数据库有此记录,session也有此对象,说明当前aLog是处于持久化状态,如果在事务提交的时候,会判断当前对象记录是否发生改变,是的话就会触发update操作。


所以,这也就是为什么aLog并没有主动调用save操作,就帮忙把它自动更新了。


重新理了一下逻辑,也调整了下代码,因为①aLog.setStatus(INIT)并不需要,多此一举了。所以把它去掉即可。


3)了解Hibernate的状态


Hibernate存在transient(瞬时状态),persistent(持久化状态)以及detached(离线状态)。


瞬时状态就是刚new出来一个对象,还没有被保存到数据库中,持久化状态就是已经被保存到数据库中,离线状态就是数据库中有,但是session中不存在该对象。


①对于刚创建的一个对象,如果session中和数据库中都不存在该对象,那么该对象就是瞬时对象(Transient)。


②瞬时对象调用save方法,或者离线对象调用update方法可以使该对象变成持久化对象,如果对象是持久化对象时,那么对该对象的任何修改,都会在提交事务时才会与之进行比较,如果不同,则发送一条update语句,否则就不会发送语句。


③离线对象就是,数据库存在该对象,但是该对象又没有被session所托管。


3

总结


虽然这个问题并不难(或者这不算问题),但是为了避免其他人或者你可能以后也会遇到的这种问题,可以很好的帮助(你)避免重蹈覆辙。


1)对于查询出来的对象,如果无需更新就不要set属性值,有时可以创建新变量来存储当前的值;
2)使用JPA(Hibernate)要注意自动会“帮你”更新数据库数据;
3)记录每次遇到的不小不大的问题,可以帮助少踩坑。


参考:
https://www.cnblogs.com/xiaoluo501395377/p/3380270.html
http://www.luyixian.cn/news_show_268613.aspx



推荐好文

1、互联网Code Review最佳实践分享

2、dubbo面试题!会这些,说明你看懂了dubbo源码

3、Kafka面试题!掌握它才说明你真正懂Kafka
4、
Netty 5.0为啥被舍弃?原因竟然是...
5、
中台之上——业务架构系列【汇总】

6、必备瑞士军刀IDEA插件,你使用了哪些

7、线上热更新代码只需3步 Arthas实战

8、Eureka源码剖析之七:架构&面试题【总结】

9、互联网工程师应该用这种姿势打印日志

10、加入:互联网基础/架构交流群




打赏
打赏
关注公众号
公众号
类别:Java| 阅读(369)| 赞 (0)
评论
暂无评论!
发表评论
昵  称:

验证码:

内  容:

    同时赞一个 赞