问题场景:
在尝试把原本在eclipse上的Java Web项目转移至Intelij idea上时,在配置文件均与eclipse一致的情况下出现了如下报错:
org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): cn.umbrella.crm_core.settings.mapper.UserMapper.selectUserByAccandPwd
at org.apache.ibatis.binding.MapperMethod$SqlCommand.<init>(MapperMethod.java:229)
at org.apache.ibatis.binding.MapperMethod.<init>(MapperMethod.java:53)
at org.apache.ibatis.binding.MapperProxy.lambda$cachedInvoker$0(MapperProxy.java:96)
at java.base/java.util.concurrent.ConcurrentHashMap.computeIfAbsent(ConcurrentHashMap.java:1708)
at org.apache.ibatis.util.MapUtil.computeIfAbsent(MapUtil.java:36)
at org.apache.ibatis.binding.MapperProxy.cachedInvoker(MapperProxy.java:94)
at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:86)
at jdk.proxy4/jdk.proxy4.$Proxy38.selectUserByAccandPwd(Unknown Source)
at cn.umbrella.crm_core.settings.service.impl.UserServiceImpl.queryUserByAccandPwd(UserServiceImpl.java:27)
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
at java.base/java.lang.reflect.Method.invoke(Method.java:580)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:354)
...
问题描述
在eclipse中,我们的项目结构如图所示,即Mapper.xml跟Mapper接口都放在src/java目录下,项目部署tomcat后运行没有任何问题,但是到了IDEA中,项目就无法找到Mapper.xml文件,在反复确认了SpringMVC及MyBatis配置文件无误的情况下,问题仍然无法解决。
原因分析:
eclipse在编译项目时会按照applicationContext-datasource.xml中配置的Mapper扫描器对Mapper.xml进行扫描而Intelij IDEA不会,这其实是两者的Tomcat部署方式不同。也就是说默认情况下,eclipse是热部署,而IDEA不是,IDEA需要先用Maven将项目构建为war包,然后复制到Tomcat等webapps目录下才能运行,而这个构建过程中,由于src/main/java不是资源目录,所以mapper.xml不会被打包至target目录中。
eclipse配置tomcat时是本质上是映射了一个tomcat的镜像在.metadata的serer.core目录下,每创一个tomcat,就生成文件名为“tmp编号”的tomcat的映射文件,创建的镜像和源tomcat就没有关系,eclipse是通过这个镜像的tomcat去运行项目。
IDEA是先把项目进行构建打包,然后将war包复制到本地Tomcat的webapps目录下运行项目。
参照:Eclipse和IDEA配置Tomcat的区别
解决方案:
直接在src/main/resources目录下新建与src/main/java中mapper接口映射的目录,将mapper.xml文件转移至resources目录下,这样在applicationContext-datasource.xml中配置的Mapper扫描器地址可以不用改变。
<!-- mapper注解扫描器配置,扫描@MapperScan注解,自动生成代码对象 -->
<bean id="mapperScanner" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="cn.umbrella.crm_core.settings.mapper, cn.umbrella.crm_core.workbench.mapper"/>
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
</bean>
另外,还有大佬提供了其他的解决方案,就是在pom.xml中配置资源目录的方法,参照下面的链接:
- (完美解决汇总)org.apache.ibatis.binding.BindingException: Invalid bound statement (not found)
- org.apache.ibatis.binding.BindingException Invalidbound statement (not found)的解决方案和造成原因分析