问题提出:昨天在稽核数据时候发现主表和明细数据不一致,查看原始数据表发现同样存在主表和明细表数据不一致,明细表明显存在重复数据,分析重复数据,一条主表记录居然最多对应90条除了主键不一样其他全部相同的明细记录,最少的也有3条明细记录。
问题解决过程:
数据保存的接口是我提供的,业务开发的同事已经不在,只好自己去找问题根源了。
1,首先确认问题是否存在。
项目上线很久了,该业务一直运行良好,没有报障,所以我开始认为是统计有问题,再三在生产数据库确认,数据重复问题确实存在,不是统计的问题。
2,找到代码位置,分析代码。
首先得找到业务对应的代码的位置,原来业务不是我开发的,漫无目的的搜索毫无用处,只好反推,从我的数据保存接口往上,Ctrl+Alt+H,出来一堆的方法调用,一看傻眼了,到底那个出问题了。
昨天下午4点开始到下班,看代码,结果很苦逼,代码不是自己写的,看起来老是怪怪的,怎么看都看不出问题,加上代码中的方法一个比一个长,一个方法从开始到结束大部分长度在600行左右,把我看晕了。
今天上午继续看代码,实话实说,我没看出问题,都看晕了,唯一看出的是代码中没有重复保存问题存在。
3,从页面上找到原始方法调用
代码没看出问题,只好在页面上把业务一个一个尝试,之所以没有一开始就从页面上点击,是因为我对业务怎么操作的不清楚,现在只剩下这种方法了,不清楚业务怎么操作的,只好请教测试人员询问业务操作流程,被测试鄙视了。
在页面上造了一笔测试数据,点击提交,查看url方法找到调用的原始方法名称,定位代码位置,第一次没有打断点,查看数据库,数据正常,没有重复数据。
换一种业务操作,试下批量操作,第一次只提交了一条记录,马上找到了方法名称,在方法上打算断点,debug运行,批量操作提交只提交1条记录,debug发现情况正常。
难道不是这个业务,不应该,就这2种操作,再测试下,这次批量提交2条测试记录,运行后没看出问题,查看数据库一看,数据库居然不止2条记录,看来就是这个业务出问题了。
4,修改代码
原始方法找到了,保存方法经测试没有问题,问题在上面,把保存方法里面的内容注释掉,再次debug,发现了一些端倪。
1,第1条记录时候没有问题。
2,第2条记录保存前居然能看到第一条记录的数据。
初步怀疑是引用引起的。原始代码简化后如下:
List<ThirdJavaBean> orderItemList = new ArrayList<ThirdJavaBean>();
for(int i=0;i<list.size();i++)
{
ThirdJavaBean ob=new ThirdJavaBean();
ob.setXXX();
orderItemList.add(ob);
ThirdJavaBean[] tbs=new ThirdJavaBean[orderItemList.size()];
for(int j=0;j<orderItemList.size();j++)
{
tbs[j]=orderItemList.get(j);
}
XXSV.saveJavaBean(tbs);
}
-----上面for循环是j<orderItemList.size();自己手写的代码,写成了i,谢谢指正。
不要问我代码为什么这么写,这不是我写的,眼尖的朋友也行发现了问题所在,第4行附近orderItemList 出问题了,由于对象引用,每次循环,下一次时候都能拿到上一次的数据,这是一个由于粗心引起的非常隐蔽的错误。
解决方法如下:
每次for循环里面都重新new 一个orderItemList,这样就不会出现上面的问题了。
结论:
1,对象在使用=赋值时候,小心原始对象的引用问题,最好每次重新new一个对象。
2,论熟悉业务的重要性。
3,错误很低级,发现不容易。