Spring boot本地运行请求正常,打包后运行正常,但是请求报错:invalid bound statement not found 的问题
问题场景
这个问题发生在我准备将一个旧项目打包部署到服务器上的时候,在服务器上运行jar包后,访问接口返回500,检查服务器日志发现抛出了异常invalid bound statement (not found)
。
项目结构
项目主要框架为Spring boot 和 mybatis-plus , 代码放在src/main/java中的某个包下,而xml文件则存在在resources/Mapper文件夹下
初步分析
按照以往的经验来说,出现该问题是由于mybatis的xml文件与mapper接口类没有建立映射关系。
于是我就启动了本地项目进行测试,但是发现本地项目可以正常请求,正常调用sql语句,一下就给整蒙了…
接着我又做了以下几个操作:
- 检查xml文件中的namespace映射,发现是正确的(其实这一步由于本地IDE启动时正常的所以基本不会错)
- 检查打包文件是否包含了xml文件,结果是正常打包进去了的。
- 重新clean -> compile -> package 打包重新部署到服务器,重新请求 =》 抛出异常
- 在本地机器直接运行jar包,重新请求 =》抛出异常
-
在进行以上操作后,很奇怪,为什么本地和jar类相同,但是二者启动后的测试却不同,显而易见,这个问题肯定是与 jar包启动方式 有关。
接着踩坑
在网上用mybatis jar包等关键词搜索了一圈,没有找到相关的文章,于是开始自己寻找原因。
根据刚刚的测试,通过IDE直接运行main方法是可以正常访问的,而打包成jar包运行jar包则会失败。
那么就去查看了直接运行main方法 与 运行jar包的区别,后来得出结论:
在通过jar包启动项目时,如果你的静态资源都打包在jar包里,那么就需要注意路径大小写的问题,如果你的静态资源是在jar外部,那大小写是否敏感就的看你运行的操作系统了。
下面的文章对于两种启动方式的研究很详细,这里附上链接,可以自行查看一下。
参考文章:SpringBoot的静态文件资源文件名称大小写敏感问题研究
原因: 个人问题
根据上面的分析结果,将存放xml文件夹的目录名称Mapper中的大写字母改成小写就可以了。
但是,这时候我想到一个问题,难道文件名必须强制要求小写?这种要求似乎太过于严苛了,不是可以通过mapper-locations配置xml扫描路径么。
所以,我又去检查了项目中的xml扫描路径配置,结果发现忘记写了…采用的是mybatis-plus的默认扫描路径,即src/main/resources/mapper/*.xml
。由于个人习惯也是放在这个目录下,但是当初创建文件夹时不小心把首字母大写了,后面发现能够运行也就没有去多想。
那么 总结下来,在我的项目中会导致出现本地IDE运行正常,打包jar包启动后mybatis的xml映射关系找不到invalid bound statement (not found)
的原因有以下几点:
- 未配置mapper-loactions属性,采用了mybatis-plus默认的路径
src/main/resources/mapper
- 存放xml文件的目录名为Mapper,首字母大写
- 本地IDE直接启动项目时,对于resources不区分大小写。对jar包启动项目时,对于resources路径区分大小写。
总结
还是个人经验不足,粗心大意,竟然忘记了配置mapper-locations,实际上通过mapper-locations属性是可以指定扫描任意目录中的Mapper.xml文件的,同时还阴差阳错的将xml文件放到了默认扫描路径下,并且把目录名首字母大写了,导致jar包启动时区分大小写时无法找到xml文件。不过还是有收获的,了解到了直接运行main方法以及jar包启动之间的区别,记录下来,提醒自己避免再犯这种错误。
需要保证xml文件在打包后成功打包进了jar包中。因为在解决问题的过程中发现许多人是出现了将xml文件放在java代码目录下导致打包时maven自动忽略的xml文件导致找不到xml文件的问题。