错误 org.apache.ibatis.binding.BindingException: Invalid bound statement (not found) 的出现,意味着项目需要xml文件来映射SQL语句,如果只使用接口进行SQL映射,不在本文讨论范围内。

  我的项目的环境是IDEA下的Maven工程,而IDEA下的MAVEN工程中有一个特点就是,在src/main/java中,只有.java文件默认会被编译,而xml文件不会被编译。(出处)

  的确这样的做法也比较符合Maven目录框架的初衷:即在src/main/java中只存放.java的源码文件。

  在使用MyBatis Generator进行逆向生成时是可以指定mapper接口和对应的xml文件的位置的,有的人也喜欢把它们指定在java目录下的同一个包(如:src/main/java/com/abc/mapper)中,而我就喜欢指定在不同的目录下(接口文件:src/main/java/com/abc/mapper,xml文件:scr/mian/resources/mapper)。我们分开讨论

一、Mapper接口文件和对应的XML在同一个目录下

  一般来说,接口文件和XML文件是同名一一对应的。

  这种情况就是要改变IDEA中MAVEN工程默认不编译src/main/java中的xml文件的行为,需要在maven的pom.xml中配置一个节点:

<project>
......
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
</resources>
</build>
</project>

  这样IDEA就会对src/main/java中的xml文件进行编译了。

  我的工程中进行相应的修改后,的确奏效了。

  但是我项目中MyBatis的核心配置文件中,配置是空的,没有指定任何xml的位置:

<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration> </configuration>

  然后发现,在Spring容器中创建SqlSessionFactory的Bean时(在applicationContext-dao.xml中),就已经指定了Mapper接口的位置:

<!-- 让spring管理sqlsessionfactory 使用mybatis和spring整合包中的 -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 数据库连接池 -->
<property name="dataSource" ref="dataSource" />
<!-- 加载mybatis的全局核心配置文件 -->
<property name="configLocation" value="classpath:mybatis/SqlMapConfig.xml" />
</bean> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.taotao.mapper" />
</bean>

  在上面的配置中,如果我去掉第二个bean,应用就无法正常启动。报错的内容大概是这样:因为那些Mapper接口没有被注册为Bean,所以在Service层中的相关类中的属性的自动注入没法完成,因为找不到那些Mapper的bean。事实上,在Spring的配置文件中使用这个MapperScannerConfigurer类我也是第一次碰到,查了一下,这个类就是进行Bean的定义工作——“从接口的基础包开始递归搜索,并将它们注册为MapperFactoryBean。 请注意,仅注册具有至少一种方法的接口; 具体类将被忽略”。

  而我自己习惯的做法是,在applicationContext-dao.xml中进行如下声明,把MyBatis的相关映射接口注册为Bean:

<!--将指定的包中所有接口当作mapper来配置,之后可以自动引入mapper类-->
<mybatis:scan base-package="com.biguo.mapper"/>

  所以需要确保把Mapper接口注册为Bean,不论用哪种方式,都是可以的,而同目录下的xml文件是被自动加载。

  第一种情况的解决方案就是这样。

二、Mapper接口文件和对应的XML在不同的目录下

  如下图,我习惯的做法是在进行MyBatis逆向生成时,把Mapper接口放在src/main/java下,把对应的XML文件放到src/main/resources下,分开存放。

  mapper接口是一定要注册为Bean的,上面提到的两种方式都可以。

  然后就是,告诉MyBatis去哪里找到哪些映射SQL语句的XML文件,最最常用的就是在MyBatis 的核心配置文件中使用<mappers>标签进行指定。官方文档也说得很清楚:MyBatsi官方文档 。

  官方文档里写了有四种方式来指定xml映射文件的位置:类路径相对资源引用(resource),完全限定的url引用(包括file:/// URL),类名或包名,下面分别举个例子:

<mappers>
<mapper resource="org/mybatis/builder/AuthorMapper.xml"/> <mapper url="file:///var/mappers/AuthorMapper.xml"/> <mapper class="org.mybatis.builder.AuthorMapper"/> <package name="org.mybatis.builder"/> </mappers>

  然而,根据这位朋友(Hern)的文章(参考出处),这四种指定方式有一定的限制:

1、当采用class、package方式时,映射文件(Mapper.xml)和接口必须命名相同,并且放在与接口同一目录下。(尽量不要采用这种方法)

2、当采用class方式时,没有SQL映射文件,所有的SQL都是利用注解写在接口上,这样就可以避免注意1的事情发生,提高维护性,不是很重要的SQL语句可以采用注解的方式,这样可以提高开发速度,重要和复杂的接口、SQL建议还是采用SQL映射文件的方式。(尽量采用这种方法)

  我什么会搜到这位朋友的文章呢?因为我自己有个问题一直没解决。

  以前一般都是用resource指定xml文件的位置,不论有多少个xml文件,都在<mappers>里一个个写出来,因为我找不到可以批量指定的方法(通配符什么的试了,没成功)(注意别忘了现在的背景是mapper接口和xml映射文件在不同的目录下)。

  Hern的文章提醒了我,可以指定一个Package来批量加载XML映射文件,但是它们必须和mapper接口在同一目录下。如果是这样,那我们又回到了上第一种情况——必须解决掉IDEA下Maven工程默认不会对src/main/java的非.java文件的行为。这样做好像也不错,也就是可以不需要批量指定,只要配置了Maven节点,mapper接口同目录下的xml映射文件就能自动加载了。

  所以现在的问题就变成了:必须在XML文件与mapper接口在不同目录下的情况下找到批量加载XML映射文件的方法。

  还真的找到了,StackOverflow(How to load mapper xml files with wildcard?)给了启发。

  方法就是在applicationContext-dao.xml注册SqlSessionFactory的bean时,设置一个"mapperLocation"属性(property),来告诉MyBatis那些XML映射文件的位置(可以使用通配符),如下:

<!-- 让spring管理sqlsessionfactory 使用mybatis和spring整合包中的 -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 数据库连接池 -->
<property name="dataSource" ref="dataSource" />
<!-- 加载mybatis的全局配置文件 -->
<property name="configLocation" value="classpath:mybatis/SqlMapConfig.xml" />
<!--批量指定mapper的xml文件的方法,此时xml无需与接口在同一个文件夹下-->
<property name="mapperLocations" value="classpath*:mapper/*Mapper.xml"/>
</bean>
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.taotao.mapper" />
</bean>

  也就是说,在同一个地方,创建了SqlSessionFactory的Bean,批量加载了XML映射文件,创建了所有mapper接口的Bean。这样做,我的MyBatis核心配置文件就仍然可以保持0配置。

  然后我也查看了SqlSessionFactoryBean的官方文档,这个类中的确有这么一个方法:

void setMapperLocations(Resource[] mapperLocations)

Set locations of MyBatis mapper files that are going to be merged into the SqlSessionFactory configuration at runtime.This is an alternative to specifying "<sqlmapper>" entries in an MyBatis config file. This property being based on Spring's resource abstraction also allows for specifying resource patterns here: e.g. "classpath*:sqlmap/*-mapper.xml".

设置将在运行时合并到SqlSessionFactory配置中的MyBatis映射器文件的位置。 这是在MyBatis配置文件中指定“<sqlmapper>”条目的替代方法。 此属性基于Spring的资源抽象,也允许在此指定资源模式,例如: "classpath*:sqlmap/*-mapper.xml"

  还能再说什么呢,Spring牛逼就完事了!!

  这个应该是最佳解决方案了,ok,任务完成~

解决 org.apache.ibatis.binding.BindingException: Invalid bound statement (not found) 以及MyBatis批量加载xml映射文件的方式的更多相关文章

  1. IDEA异常解决: org.apache.ibatis.binding.BindingException: Invalid bound statement (not found)

    有时候解决问题不仅仅是解决问题.-----jstarseven 最近因为开发需要,需要搭建一个ssm开发框架,采用了开发工具IDEA. 整合完了SSM开发框架之后,发布的时候出现org.apache. ...

  2. 完美解决: org.apache.ibatis.binding.BindingException Invalid bound statement (not found)

    异常描述: org.apache.ibatis.binding.BindingException: Invalid bound statement (not found) 原因: springboot ...

  3. 解决org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): com.xyfer.dao.UserDao.findById

    在使用Spring整合MyBatis的时候遇到控制台报错:org.apache.ibatis.binding.BindingException: Invalid bound statement (no ...

  4. 解决org.apache.ibatis.binding.BindingException: Invalid bound statement (not found)...

    在IDEA中将xxxMapper.xml文件创建在(src/main/java)目录中,运行报错:org.apache.ibatis.binding.BindingException: Invalid ...

  5. 解决org.apache.ibatis.binding.BindingException: Invalid bound statement (not found)错误

    我调这个bug调了一天多,在网上搜索的检查namespace,package等,都没有错.错误提示是没有找到xml文件,我就纳闷了,为什么找不到呢?后来才发现,原来是resource中奇怪的目录为题, ...

  6. Request processing failed; nested exception is org.apache.ibatis.binding.BindingException: Invalid bound statement

    原因: 此异常的原因是由于mapper接口编译后在同一个目录下没有找到mapper映射文件而出现的.由于maven工程在默认情况下src/main/java目录下的mapper文件是不发布到targe ...

  7. Java报错:org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): com.sirifeng.babytun.dao.GoodsDAO.findById

    前言 最近学vue学得差不多了,想来搭个项目实战一下,结果刚开始搭建SSM框架的时候就来到了我们最喜欢的debug环节 org.apache.ibatis.binding.BindingExcepti ...

  8. MyBatis笔记----报错:Exception in thread "main" org.apache.ibatis.binding.BindingException: Invalid bound statement (not found)解决方法

    报错 Exception in thread "main" org.apache.ibatis.binding.BindingException: Invalid bound st ...

  9. maven 项目报错org.apache.ibatis.binding.BindingException: Invalid bound statement (not found)解决

    idea在使用maven构建的项目中使用mybatis时报错org.apache.ibatis.binding.BindingException: Invalid bound statement (n ...

随机推荐

  1. iframe窗口嵌套,子窗口跳转重叠在父窗口的问题

    window.top //最顶层窗口 window.self //当前窗口 window.parent //父级窗口 "window.location.href"."lo ...

  2. SVG-概述/容器与通用属性

    参考: SVG 图像入门教程 MDN SVG SVG教程 SVG入门-踏得 工具: svg在线编辑 概述 SVG 是一种基于 XML 语法的图像格式,全称是可缩放矢量图(Scalable Vector ...

  3. cookie和session-csrf防护-中间件

    cookie概念: 是由服务器生成,保存在浏览器端的一小段文本信息. cookie特点: 1) cookie是以键值对进行存储的. 2) 浏览器访问网站时,会将本地保存的跟网站相关的所有cookie发 ...

  4. jq删除标签

    <script>$(function(){ $("div").remove()})</script>

  5. Python3之高阶函数filter

    Python内建的filter()函数用于过滤序列 和map()一样,filter()也接收一个函数和一个序列.和map()不同的是,filter()把传入的函数依次作用于每个元素,然后根据返回值是T ...

  6. iOS-二维码扫描界面(转)

    网址学习:http://blog.csdn.net/linux_zkf/article/details/7724867     二维码扫描界面自定义 作者:朱克锋 邮箱:zhukefeng@iboxp ...

  7. 02.提交bug

    写代码最烦的也就是修复bug了,虽然这个避无可避…………………… a. bug的严重级别设置 1级:影响主要流程 ->在bug 的影响下,主流程 测试无法向下进行 2级:影响核心功能 -> ...

  8. Spring 使用单选按钮

    模型层需要提供数据选项,设置错误信息 关键代码 @NotNull(message = "请选择性别") private String gender; 控制器层需要在显示视图前,通过 ...

  9. eclipse设置html js css自动提示

    eclipse也可以像Visual Studio 2008那样完全智能提示HTML/JS/CSS代码,使用eclipse自带的插件,无需另外安装插件,具体步骤如下 1.打开eclipse→Window ...

  10. OpenCV Python 4.0安装

    1.安装OpenCV-Python 如果你是第一次使用OpenCV Python开发包,想要安装OpenCV Python4.0只要执行如下命令行即可: pip install opencv-pyth ...