1.问题描述
在谷粒商城的菜单管理需求中出现了在新建二级目录后继续新建三级目录无法显示的bug。
比如我在手机菜单下新建一个测试的二级菜单,这是可以显示的,如下图
但是,在新建的测试菜单下新建一个测试1的菜单就无法显示了,如下图。
我们首先去寻找问题的原因。
2.寻找问题原因
首先在数据库去查看是否有这两条数据。
数据库是有这两条数据的。
我们再来看看数据有没有什么问题
我们可以看到二级目录的cat_id跟三级目录的parent_id是对不上的。初步怀疑是这个原因。
我们先暴力的把二级目录的cat_id跟三级目录的parent_id改成相同看看究竟是不是这个原因。
现在改成一样的了,我们去前端看看是否能显示。
发现前端还是不显示测试1这一个三级目录。
我们再去数据库找找原因,仔细观察数据库,我们发现了pid为127及以下的菜单目录都有显示,但是pid为127以上的目录就不显示了。
所以应该的代码的问题,我们去菜单查询的代码去看看
发现parent_cid和cat_id的判断是用==来判断的。而cat_id的类型的Long的包装类型,是一个引用类型。在用==判断的使用是比较值以及地址。而Long类型的的-128~127是从数组里面拿的,是基础类型,只是比较值,而128以后的值就是包装类型,值和地址都比较,一个值为128的parent_id和128的cat_id在进行用==比较的时候由于地址不一样,导致return false。所以这里应该用equals()方法进行比较,Long类型的eauals()方法是被重写了的,只是比较值的大小,不比较地址。我们把==换成equals()试试效果
测试1和之前cai_id值为128后不显示的的菜单都成功显示了。
我们从头来试一下。
在数码一级菜单下加一个测试2的二级菜单
测试2二级菜单下加一个测试3的三级菜单
我们来看看结果
没有?难道翻车了?别急,我们好像忘了上面二级菜单的cat_id和三级菜单的parent_id不同的问题了。
我们按F12去控制台看看后端传过来的值和前端得到的值有没有什么不同
经过调查发现后端传过来的cat_id为1567914075364986882,但是前端自动转换成了1567914075364987000。
经过研究发现,Long类型的值在后端传给前端的时候会发生精度损失,这就导致了二级菜单的cat_id和三级菜单的parent_id不同。那怎么办呢?
很简单,换一个不会发生精度损失的类型就可以了,那问题来了,什么类型传值最安全呢?不会发生进度损失呢?答案当然是我们的String啦!!所以我们只要把后端从数据库拿到的cat_id转换成String类型的值就可以了。
转成String后,我们来看看前后端传值是否一样。
OK,前端拿到的值和后端传来的值一样,我们来看看这个问题有没有解决。
在测试2的二级菜单下新建一个测试4的三级菜单
完美解决,我们在去数据库看看。
二级菜单的cat_id和三级菜单的parent_id相同,完结撒花。