这两天都在忙着补录数据,基本已补录OK,甚好没对系统造成太大影响。简单梳理一下事件经过,望对各位初入Java无甚经验的程序猿能起到一个很好的警示作用。
由于该系统要做一次大变更,各种报文规范进行了一次新更改,所以就由我带着刚入职的新同事一起完成该项工作,三月份的时候,基本代码已编写完毕,剩下的调试工作,就交给了新同事(主要配合人行、财政、机构部的人一起),检测代码异常或者漏洞。
代码修改注释一定记得备份.png这个也没什么难度,所以我就投入到了其他的工作当中,只等财政通知上线。经过机构部进行测试(反复测试N多遍),同意上线变更。上周五晚上,进行了代码变更,周一的时候,有数据接入进来,正常的做业务,待下午的时候,系统退款异常,检测数据,发现数据库有一个字段为空值。
private void parseFmt5201List(Element ele, List<EcfnPayList> ecfnPayList) throws ParseException {
@SuppressWarnings("unchecked")
List<Element> eles = ele.elements("Detail");
for (Element e : eles) {
EcfnPayList epl = new EcfnPayList();
epl.setStatus("0");
@SuppressWarnings("unchecked")
List<Element> list = e.elements();
for (Element ee : list) {
/* 支付明细Id */
if ("Id".equals(ee.getName())) {
epl.setPayListId(ee.getStringValue());
}
/* 财政直接支付凭证Id */
else if ("VoucherBillId".equals(ee.getName())) {
epl.setVoucherBillId(ee.getStringValue());
}
/* 财政直接支付凭证单号 */
else if ("VoucherBillNo".equals(ee.getName())) {
epl.setVoucherBillNo(ee.getStringValue());
}
/* 支付申请序号 (原本需要删除的字段 取报文明细单VoucherDetailNo的值) 0421 ykx*/
else if ("VoucherDetailNo".equals(ee.getName())) {
// epl.setVoucherNo(ee.getStringValue());
}
/* 资金性质编码 */
else if ("FundTypeCode".equals(ee.getName())) {
epl.setFundTypeCode(ee.getStringValue());
}
………………………………………………
/* 备注 */
else if ("Remark".equals(ee.getName())) {
epl.setRemark(ee.getStringValue());
}
/* 实际支付日期 */
else if ("XPayDate".equals(ee.getName())) {
if (ee.getStringValue() != null && ee.getStringValue().trim().length() == 8) {
epl.setxPayDate(ee.getStringValue());
}
}
/* 预留字段1 */
else if ("Hold1".equals(ee.getName())) {
epl.setHold1(ee.getStringValue());
}
/* 预留字段2 */
else if ("Hold2".equals(ee.getName())) {
epl.setHold2(ee.getStringValue());
}
/* 预留字段3 */
else if ("Hold3".equals(ee.getName())) {
epl.setHold3(ee.getStringValue());
}
/* 预留字段4 */
else if ("Hold4".equals(ee.getName())) {
epl.setHold4(ee.getStringValue());
}
/* 新增报文 */
else if ("VoucherDetailNo".equals(ee.getName())) {
epl.setVoucherDetailNo(ee.getStringValue());
} else if ("GovExpEcoCode".equals(ee.getName())) {
epl.setGovExpEcoCode(ee.getStringValue());
} else if ("GovExpEcoName".equals(ee.getName())) {
epl.setGovExpEcoName(ee.getStringValue());
} else if ("DepExpEcoCode".equals(ee.getName())) {
epl.setDepExpEcoCode(ee.getStringValue());
} else if ("DepExpEcoName".equals(ee.getName())) {
epl.setDepExpEcoName(ee.getStringValue());
} else if ("TrackingID".equals(ee.getName())) {
epl.setTrackingID(ee.getStringValue());
}
}
ecfnPayList.add(epl);
}
}
我发现数据库VoucherDetailNo这个字段值为空,而同时新增加的字段GovExpEcoCode、GovExpEcoName等等都有值,一下子就有些不淡定了,怎么可能单单略过VoucherDetailNo字段不解析呢?
先暂停读取报文自动任务,截了一段xml报文至测试环境进行本地测验,发现没什么问题,可以读取VoucherDetailNo的值,可是生产为什么没有读取该值呢?变更还是自己亲自进行的,按理说不会有错,于是截取生产class文件,进行反编译,结果就得到了上面的代码。
/* 支付申请序号 (原本需要删除的字段 取报文明细单VoucherDetailNo的值) 0421 ykx*/
else if ("VoucherDetailNo".equals(ee.getName())) {
// epl.setVoucherNo(ee.getStringValue());
}
/* 支付申请序号 */
// else if ("VoucherNo".equals(ee.getName())) {
// epl.setVoucherNo(ee.getStringValue());
//}
这一段真是坑死我,这一段是被我注释了的(第2个代码块),不知道为什么就被同事取消改为了代码块1。后来问了一下他原因,他说:财政人员说原VoucherNo的值跟新VoucherDetailNo的值时一样的,所以他就保留了。保留也就保留了,为什么这个地方要加注释呢?
// epl.setVoucherNo(ee.getStringValue());
[这个地方加了注释导致的结果就是==无法Update明细单VoucherDetailNo的值为VoucherNo]
注释就注释了,可是我比对SVN代码与我本地代码的时候,发现一模一样,结果拿该同事本地代码与SVN代码比对,发现他的这一个地方与SVN有异同。我向他递了一个大大的问号,他说:测试过程中忘了同步了!
上线变更的class文件是该同事提供的,我检查了变更文件,不多不少,所以就上线生产了(这个地方我也有责任,该同事算个新手,没什么项目经验,但功底还是挺不错的)我就问他,你这么改VoucherDetailNo有值吗?他说有值,我看了看测试环境数据库,该字段还真有值。然后我问他,你这段代码什么时候改的?上测试环境了吗?他说记不清了。。。。估计他后面不注意改了改,自己又忘记了,所以把编译好的class文件发给了我,就导致该次变更异常。
这种情况其实也正常,在测试过程中,基本也是他负责代码的调试(主要是数据验证、报文规范检查),所以我就发了这样一段代码给他:
public static void main(String[] args) {
Example("2");
}
public static void Example(String msg) {
if (msg.equals("1")) {
System.out.println("1");
} else if (msg.equals("2")) {
// System.out.println("2");
} else if (msg.equals("888")) {
System.out.println("888");
} else if (msg.equals("111")) {
System.out.println("111");
} else if (msg.equals("2")) {
System.out.println("Hello World");
}else {
System.out.println("nothing");
}
System.err.println("end----");
}
我问他:你说会输出Hello World
吗?他犹豫了一下还是点了点头,结果他自己跑该代码的时候,也发现自己问题所在了。
如果多个else if
并列,只要第一个if
条件成立,后面的else if
和else
都不会执行,即使满足else if
的条件也不会执行。
如果多个if
,那么最后的else
会执行;else
与最近的if
匹配,包括else if
的if
,if
满足条件执行,最后的else
满不满足条件,都执行。
public static void main(String[] args) {
MoreIf("2");
}
public static void MoreIf(String msg){
if (msg.equals("1")) {
System.out.println("1");
}
if (msg.equals("2")) {
System.out.println("2");
}
if (msg.equals("111")) {
System.out.println("111");
}
if (msg.equals("888")) {
System.out.println("888");
} else if (msg.equals("666")) {
System.out.println("666");
} else {
System.err.println("Hello World");
}
}
执行结果.png
由于VoucherNo为空,VoucherDetailNo也为空,是没办法直接修改数据了,只好把当天的日志拿下来,写了一段程序,读取日志中的xml报文,输出sql的Update语句进行变更,可看下一篇!
网友评论