如何去寻找解决bug?(以Mapped Statements collection does not contain value for xxx的异常为例)

简介: 如何去寻找解决bug?(以Mapped Statements collection does not contain value for xxx的异常为例)

引言

众所周知,我们完成一个项目的时间三分之一是用来写代码的,而剩下三分之二的时间是用来调试寻找解决bug的。


那么如果能提高解决bug的效率就能大大加快项目的开发速度。


下面我以mybatis框架报的Mapped Statements collection does not contain value for xxx的异常为例,来说说如何有目的,有效率地解决bug。


环境:mysql+mybatis框架+java编写的maven项目


想看具体项目的可以去看我项目实战专栏里的图书信息管理系统(一个适合刚入行新手的练手项目)


链接:https://blog.csdn.net/qq_46101869/article/details/106910497


案例

好了回归正题,


q4.png

上图是我在调试遇到的一个问题,可以看到程序报了Mapped Statements collection does not contain value for xxx的异常,这很明显是mybatis框架报的异常,通过报错信息大概猜测是mybatis XXX容器内不包含我写的Mapper(因为那时候我还不知道Mapped Statement是什么东西),然后我就无脑将这段报错信息贴到百度上搜,确实有很多博客记录了此错误及解决方法,我截了一个下来,如图:


q3.png


但实际上我按照博客上一个个去做,并没有解决问题,这时候我已经花了一个下午时间去查找,问题没解决,倒是把mybatis框架复习了一遍。


苦思之下,我开始逐步调试,以下是我的思考过程:


因为问题肯定出在mybatis框架上,所以我逐步调试,但是呢,我又不懂mybatis源码,看得云里雾里。不过我之前自学Java的时候,跟着视频写过一个类似mybatis的框架------SORM框架(不过功能肯定没mybatis框架复杂,是个小型版的框架),做完后学了其他知识后,自己又回头帮它迭代优化了一下,增加了新的功能,优化了结构。


q2.png


这段经历让我能大概理解mybatis框架的一些行为,比如在这个地方我就注意到了mappedStatement对象size为0。这时我就猜测这应该是框架本身并没有读取到我写的sql语句,那是由什么造成的呢?


q1.png


这时候我就开始测试,不用接口类的方式(因为创建实体类也是mybatis框架底层做的),为了缩小问题的范围,我们采用原始的方式(但不是原生jdbc),发现还是这个错误,然后我开始怀疑mapper注册问题



w3.png

这里我原本是采用包扫描的方式注册,然后我开始尝试用指定路径文件方式去注册



w2.png

然后异常变了,说找不到这个文件


好家伙,之前包扫描的时候报的是Mapped Statements collection does not contain value for xxx,现在直接报没找到这个文件!


这时候我就开始思考为什么?


为什么我用包扫描的方式就不报错呢?而用具体的文件路径就报错呢?


真的是包扫描时找到了xml文件而具体文件路径没找到吗?


不对,不是这样的,换个角度讲,包扫描没扫描到,会报错吗?不会,那问题区间缩小,很可能就是因为xml文件路径的问题。而其他配置文件是找到了的,不然它根本不会提示找不到(路径是写在mybatis-config.xml文件里的),既然我们确定了问题所在,这时候我们就需要尝试改变路径


w1.png


这时候我再去查博客,搜索的不是异常信息,而是配置文件的路径该怎么写?


在搜索的过程中我逐渐意识到我的项目结构可能与别人不同,所以我在搜索时加了Maven限定词,好家伙,不搜不知道,一搜我找到了原因所在。


原来Maven项目编译时会把文件全都输出到Target文件夹下面


q5.png


而默认情况下配置文件只会把resource文件夹下面的配置文件输出,这就造成Java文件夹下面的Mapper文件根本不会输出到target里,这样当然就找不到了,于是我修改了Maven项目中核心配置文件pom.xml信息,加入了下面的配置



q4.png然后呢?


还是找不到…


本着不抛弃不放弃的精神,我开始关注target文件夹的文件结构



q3.png

什么,居然有两个com.dreamchser,这是为什么呢?


然后我开始测试加百度,然后发现了IDEA的神坑之处------当我们创建一个包时,com.dreamchser和com/dreamchaser是不同的!


com.dreamchaser就是指第二个圈里的包,com/dreamchaser指的是第一个圈里的包


.和/的差别真的是坑死我我了!


我仔细思考了下,之前查询博客的时候,确实有博客提到idea中创建包时/和.是不一样,但当时我以为我的mapper是被读取进去了,所以没在意,只是检查了其他部分,知道后面调试运行底层源码时MappedStatement这个对象的size=0,通过字面意思猜测mybatis实际上是没有读取进去的,进而开始了这方面的排查,最终找到了原因。


q2.png


如果用使用动态代理改造CRUD的方式,用接口实现,这意味着接口路径要和xml中那么namespace中的值一致,而在mybatis配置中mapper注册的时候路径要写的是被打包进target/classes下的路径,注意.和/ 的区别


q1.png


总结

当我们遇到一个bug的时候,不要二话不说就把异常信息Ctrl+C,Ctrl+V去百度。这确实可能会让你解决问题,但是有很大几率是你搜遍了网上的解决方式也没有解决,因为通常一个框架的同一个异常其实是有很多原因,你就会像无头苍蝇那样乱转,运气好可能会解决问题,运气不好就会到处碰壁。虽说面向百度编程这句话不假,但是我们更要做的是知道问题出在哪里。


我们遇到bug,遇到异常所需做的第一件事就是思考为什么会报错,去定位问题的所在。


而在如何定位问题呢?这需要你对程序,对这个框架的运行原理有一定的了解,有对判断问题的直觉和思维。


当然我们也可以利用一些技巧,比如看报错的信息(看不懂英文就网上翻译),根据报错信息来猜测问题的原因;还有就是切换思维,我们应该以程序的思维去思考,如果要这么做程序会怎么做?它需要什么条件?什么情况下会报这种错误?当然其实更有效更简单粗暴的做法就是调试,你可以看看它在那个地方停下报错了,看看调试过程中配置是否加载完全了。


然后我们再有目的地去百度,把你思考得到的关键词(或者怀疑可能出错的地方)当成限定词,你这样再去百度的话,大概率会得到你想要的答案,同时这一思考过程也会大大提升你对知识、工具的理解,锻炼你自己的能力,这点也是极为重要的!


欢迎在评论区留下你的意见和建议,我们可以一起探讨技术,共同进步!

相关文章
|
4月前
|
XML 缓存 API
【Azure API 管理】使用APIM进行XML内容读取时遇见的诡异错误 Expression evaluation failed. Object reference not set to an instance of an object.
【Azure API 管理】使用APIM进行XML内容读取时遇见的诡异错误 Expression evaluation failed. Object reference not set to an instance of an object.
|
7月前
|
算法 Java C++
Java中的标号(Labels)与标签语句(Labeled Statements)深入解析
Java中的标号(Labels)与标签语句(Labeled Statements)深入解析
231 0
|
7月前
|
DataWorks 数据管理 大数据
DataWorks操作报错合集之DataWorksUDF 报错:evaluate for user defined function xxx cannot be loaded from any resources,该怎么处理
DataWorks是阿里云提供的一站式大数据开发与治理平台,支持数据集成、数据开发、数据服务、数据质量管理、数据安全管理等全流程数据处理。在使用DataWorks过程中,可能会遇到各种操作报错。以下是一些常见的报错情况及其可能的原因和解决方法。
122 0
|
7月前
|
SQL JSON Java
【bug日记】已解决:Invalid bound statement (not found): 找不到对应的Mapper映射类
【bug日记】已解决:Invalid bound statement (not found): 找不到对应的Mapper映射类
|
SQL 存储 Java
关于PageHelper何时执行select count(0) from xxx查询?(结论+源码Debug分析)
关于PageHelper何时执行select count(0) from xxx查询?(结论+源码Debug分析)
关于PageHelper何时执行select count(0) from xxx查询?(结论+源码Debug分析)
|
SQL 索引
【笔记】开发指南—DAL语句—CHECK GLOBAL INDEX
您可以使用CHECK GLOBAL INDEX语句检查主表和索引表的数据是否完全一致,并修订不一致的数据。
开发指南—DAL语句—SET—SET语句变量设置
您可以通过SET语句设置各类变量,包括用户自定义的变量、session变量和global变量。
117 0
|
Java 数据库连接 数据库
jdbc利用java反射实现结果集得到处理:bug:argument type mismatch
jdbc利用java反射实现结果集得到处理:bug:argument type mismatch
337 0
jdbc利用java反射实现结果集得到处理:bug:argument type mismatch
|
SQL 索引
开发指南—DAL语句—CHECK GLOBAL INDEX
您可以使用CHECK GLOBAL INDEX语句检查主表和索引表的数据是否完全一致,并修订不一致的数据。
114 0
|
Java API 容器
Java Review (二十四、集合-----Collection 接口)
Java Review (二十四、集合-----Collection 接口)
93 0