springboot使用mybatis报错Invalid bound statement (not found)对应的坑
背景及现象
近期做的一个springboot项目在本地环境运行时很正常,但打包部署到现场事报错如下:
分析过程
步骤1–排查是否打包问题
根据多年编程经验,这个报错我有90%的把握是打包的时候没有把mapper.xml打进去,于是我满怀信心的打开pom文件,准备加一手对xml的打包配置。当我把pom文件拖到底部的时候,发现打包的配置竟然莫得问题!!!!
此时的我菊花一紧,顿感不妙。不过不死心的我还是打开了给现场的包,shit 果然是打进去了,看来此路不通!
步骤2–排查是否是mapper接口和mapperxml写法问题
小样,既然不是打包的问题,那要么是xml中的namespace指定错了,要么就是mapper的方法名跟xml中的id对不上,要么就是参数、返回值啥的两边对不上,反正肯定是这两文件没对上,于是赶紧打开了xml
又打开了mapper
额,瞅了10分钟,好像也莫得问题。。。(后来反思,对这个步骤的排查简直是拖了裤子放屁-完全没必要,因为我在idea里运行正常呀,要是这问题,本地肯定报错了)。
步骤3–百度确认是mapper接口名与xml文件名不一致
他喵的,不科学啊,遇到玄学了?肿么办?如果看到这你也跟我一样还没发现问题,那说明你也吃了没读mybatis源码的坑,哈哈哈。
我可不轻易相信世上有这么多玄学,但我又莫得办法了,预计我使出了我的杀手锏—找度娘!事实证明,度娘还是有用的,我找啊找,找到了希望:
mapper的接口名必须与xml文件名一模一样!!!
mapper的接口名必须与xml文件名一模一样!!!
mapper的接口名必须与xml文件名一模一样!!!
重要的事说三遍(那篇博客找不到了,但是就这几个字)
这位大神没说原因,我也不知道原因,但是我选择相信他,因为我发现我的mapper名和xml文件名真的不一样。于是我将xml的小写t改成了大写T—本地打包—java -jar启动—打开浏览器—访问系统,数据加载出来了!!!
结论
- 如果springboot中没有配置mybatis.mapper-locations指定xml的扫描路径,那么xml的文件名必须要跟mapper的接口名一模一样
- 我太菜
为什么
mybatis基础知识
咱们可以没有仔细研究过mybatis源码,但咱们不能不知道mybatis的大概原理:一方面,在应用启动的时候mybatis会扫描相关的mapperxml并根据xml配置的namespace+id对配置的sql进行缓存。另一方面,service在调用mapper接口方法时,根据mapper接口类包名+接口名+方法名去mybatis缓存找,如果找到了就根据缓存的sql查询数据库,如果没找到就会报上诉错误。
找mybatis缓存sql源码
从这能看出来,如果配置文件没有指定mapperxml的路径,那mybatis也不知道xml在哪儿,那聪明的他就默认了一个规则:即根据mapper接口来找mapperxml,具体怎么找,咱们接着往下看(啥?怎么知道mapper接口?@MapperScan和@Mapper白写啦?)
我非得看看怎么缓存的!!!
看到这,终于真相大白,原来mybatis在用户没有指定mapperxml路径时,是根据mapper接口名+.xml作为xml的路径,所以如果两个文件名不一样肯定就加载不到xml啦
为什么idea里不区分大小写
看到上面源码里如何获取xml文件了吗?
inputStream = Resources.getResourceAsStream(type.getClassLoader(), xmlResource);
我就懒得敲代码了,看这个大哥的实验结果:
没看懂?来个AI智慧问答结果吧:
至此,所有的解释都通了,下班!!!
总结
- 使用mybatis,要养成配置mapper-locations的习惯,这个原理可以自行研究一下
- idea做的有些完美了,差评
- 多读书真的能避免玄学的发生~