Fork me on GitHub

第三个任务

第三个任务

任务如下:

img

查找源文件:

然后就是找到这个功能按钮所对应的源文件:

img

img

打开源文件:

在eclipse中搜索ImpactAnalysisImportProcessor可找到ImpactAnalysisImportProcessor.java文件,这就是该按钮对应功能的源文件。

开始测试:

首先将pms上面的附件下载下来,然后运行本地测试系统,导入文件测试,并跟着代码debug了一遍,可是没发现任何错误,也能直接生成result文件,并没有存在空指针错误。

img

于是找到了标哥,标哥说这个问题是发生在生产环境下的,要在生产环境才看的到问题,给了我一个账号,登录生产环境,果然看到了空指针错误:

img

看到了报错的行数,就开始在java源文件里面看对应的代码。

可是出错的源文件在本地测试环境一直没有任何问题,在生产环境又报错,而且也没有办法对生产环境进行debug,这就是这一次任务最难的点。把整一个源文件看了一遍,也没有发现什么毛病,于是标哥叫我安装一下数据库,在数据库里面看看能不能做文章。于是就开始了安装oracle跟plsql的路。

安装Oracle与plsql

​ 由于我笔记本之前安装过Oracle,就想直接试试能不能用plsql直接连接上,可是试了好多次都不行,只好在标哥那里拿来了相同版本的Oracle以及plsql,把原来的全部卸载掉重新来。

下面是彻底卸载Oracle的方法:https://jingyan.baidu.com/article/922554468d4e6b851648f4e3.html

plsql安装方法很简单,只需要一直点击下一步就可以了。

然后就是安装Oracle:

安装包

img

在这个安装界面选择第二个,然后一直下一步即可。

环境变量

安装Oracle之后需要配置环境变量ORACLE_HOME和TNS_ADMIN环境变量:(在这里被坑了好久,一点要配置好环境变量,路径要对)

img

img

然后打开plsql:

img

点击取消按钮进入主界面:

img

点击工具->首选项:

img

在红框位置配置好两个路径,然后重启plsql。

可是重启之后发现没有读取到远程数据库,一看是因为还没有替换tnsnames.ora文件,于是在标哥那里拿来了这个文件,替换掉D:\app\Simple_Y\product\11.2.0\client_1\network\admin目录下的tnsnames.ora文件,重启plsql,就可以读取到远程数据库了。

数据库连接

这时候在eclipse运行系统,然后导入excel文件解析,查看控制台消息,可以得出是哪一个数据库用户:

img

然后查看inventory_main项目的pom.xml文件

img

可以看到对应的数据库用户和密码。然后就用这个账户登录plsql:

img

连接上数据库之后(记得断vpn),点击下面的小按钮:

img

选择新建sql窗口,然后就可以对表进行查询了。

查找问题

下面的问题就是找到数据库中对应报错行的那个数据,而Java文件报错的行数为171行,找到对应的代码:

mapmo.put(“A_DEVICE”, aDevice==null?””:aDevice.getValue(“STANDARD_NAME”).toString());

意思也不难理解,就是在aDevice对象中获取key值为STANDARD_NAME的value值,放入mapmo对象中,但是debug到这里发现是读取得到对象的,并没有出现空指针错误,所以需要在数据库中找到这个数据,将它置为空,看看能不能出现空指针问题。然后标哥教了我底层元数据api操作数据库的原理:

1
2
3
4
5
6
7
> QueryCriteria qc = new QueryCriteria("SERVICE");
> qc.addAssembleFragment("[SERVICE_END_A_DEVICE][SERVICE_END_Z_DEVICE]");
> qc.addExpression(QueryExpressionUtil.equals("ID", servId));
> List<MetaObject> services = metaService.query(qc).getList();
> //上面的就是公司操作数据库的api,一开始一直看不懂
> //下面解释具体的意思:
>

>

1
2
3
> --QueryCriteria qc = new QueryCriteria("SERVICE");
> select * from xm_entityspec m where m.code = 'SERVICE';
>

>

上面这两句是等同的,在查询结果我们可以看到service对应的表名:

img

下面的是等同的:

1
2
3
4
> --qc.addAssembleFragment("[SERVICE_END_A_DEVICE][SERVICE_END_Z_DEVICE]");
> select * from xm_relationspec m where m.code = 'SERVICE_END_A_DEVICE';
> select * from xm_relationspec m where m.code = 'SERVICE_END_Z_DEVICE';
>

>

img
img

由于我们不知道两个ID分别是对应哪一个,所以需要下面的查询语句来确定:

select * from xm_entityspec m where m.id in (2310000000,1020000000);

在xm_entityspec–实体规格描述表中查询它们分别对应什么:

img

可以看到两个ID分别对应设备和产品服务以及他们的数据表。

接下来就是:

1
2
3
4
5
> --根据servid查到service实体的数据
> select m.a_device_id,m.* from RM_SERVICE m where m.id = '441020000000001125355060' ;
> --根据service实体数据的a_device_id查询device实体的数据
> select m.standard_name,m.* from CM_DEVICE m where m.id = 441020000000001083663191;
>

>

到这里就可以找到STANDARD_NAME属性的值了,在这里将STANDARD_NAME属性置为空,然后运行系统看看会不会报空指针错误。

1
2
3
4
5
> --置空
> update CM_DEVICE set standard_name = '' where id = 441020000000001163583121;
> --查询结果
> select m.standard_name,m.* from CM_DEVICE m where m.id = 441020000000001083663191;
>

>

img

ok,成功置空了,然后重新启动系统,清空浏览器缓存,重启数据库,终于如愿以偿地看到了空指针异常。

解决问题

看来已经找到了问题了,让我们再来看看报错的代码行:

1
2
> mapmo.put("A_DEVICE", aDevice==null?"":aDevice.getValue("STANDARD_NAME").toString());
>

>

当aDevice.getValue(“STANDARD_NAME”)不存在的时候,系统就会发生空指针异常,于是我百度了一下:

map 允许null键null值 你的value引入的是一个变量吧 这个变量获取到的值为空 会报空指针异常,可以对这个变量做一个判断不就行了

是的,问题终于有突破口了,然后就对这一行进行重写:

1
2
3
4
5
6
> mapmo.put("A_DEVICE", aDevice==null?"":aDevice.getValue("STANDARD_NAME").toString());
> ->
> if(aDevice!=null && aDevice.getValue("STANDARD_NAME")!=null){
> mapmo.put("A_DEVICE", aDevice.getValue("STANDARD_NAME").toString());
> }
>

>

加入对aDevice.getValue(“STANDARD_NAME”)的判空处理,重新运行系统,完美通过,终于把这个问题解决了。

然后svn同步本地代码,更新代码,提交自己的修改,在pms网站上提交补丁,问题解决。

img

这次的问题主要是在数据库方面遇到了不少阻碍,对Oracle数据库无从下手,要看懂元数据操作的api,根据其对应的select语句找到想要的数据,才能开始动手。

下面是标哥说的比较重要的三个表:

xm_entityspec –实体规格描述表xm_relationspec –实体规格关系描述表xm_entitydescriptor –描述实体规格对应哪些数据表,以及数据表有哪些属性底层元数据api的实现,是基于上面3个表的,要了解元数据api,上面3个表是比较重要的

坚持原创技术分享,您的支持将鼓励我继续创作!
-------------本文结束 感谢您的阅读-------------