文章目录
- 一、背景与问题描述
- 二、原理与思路
- 三、具体配置示例
- 四、验证与注意事项
- 五、总结
一、背景与问题描述
在使用 MyBatis 进行开发时,一般会将 Mapper 接口(.java) 存放于 src/main/java,而将对应的 Mapper XML(.xml) 存放于 src/main/resources 下,以便在 Maven 打包时,.xml 文件能够自动复制到 target/classes 目录,最终纳入 classpath 中。
如果因项目结构或其他原因,需要将 Mapper XML 与 Mapper 接口 放置在同一目录(即 src/main/java/com/xxx/dao),就会遇到下列问题:
默认情况下,Maven 只编译
src/main/java中的.java文件,并不会把.xml文件复制到target/classes。结果是 MyBatis 在运行时无法在 classpath 中找到对应的 XML 映射文件,导致出现 “Invalid bound statement (not found)” 或 “Could not find mapper file…” 等错误。
为解决此问题,需要修改 Maven 的资源复制配置,让 src/main/java 中的 .xml 文件也被视作资源文件,编译打包时一并放入 target/classes。
二、原理与思路
- Maven 资源(resources)机制
- 默认情况下,Maven 会将
src/main/resources目录下的所有文件拷贝到target/classes,因此在运行或打包(jar/war)时,这些文件会处于 classpath 内。 - 而
src/main/java目录下通常只放置.java文件进行编译,.xml、.properties等非.java文件不会自动复制到target/classes。
- 默认情况下,Maven 会将
- 将特定目录或文件纳入资源
- Maven 提供
<resources>配置,让我们可以对任意目录执行资源复制,也可以通过<includes>/<excludes>来筛选文件类型。 - 只要在
<resources>中添加一个<resource>块,指定directory=src/main/java并include=**/*.xml,就能让.xml文件也被复制到target/classes。
- Maven 提供
- MyBatis 加载 Mapper XML
- MyBatis 需要在 classpath 中找到 Mapper XML 文件,无论是通过
mapperLocations=classpath*:**/*.xml方式,还是在mybatis-config.xml里<mapper resource="...">方式,都依赖文件实际存在于 classpath。 - 因此,只有当 Maven 把
.xml复制进target/classes后,MyBatis 才能在classpath中正确读取这些文件。
- MyBatis 需要在 classpath 中找到 Mapper XML 文件,无论是通过
三、具体配置示例
在你的项目的 pom.xml 中,找到 <build> 节点,添加(或修改)如下 <resources> 配置:
<build><!-- 项目打包名称,可不关注 --><finalName>intelligenceCommand</finalName><resources><!-- 默认资源目录,保留不动。如果你没有此段,可自行添加 --><resource><directory>src/main/resources</directory><includes><include>**/*</include></includes></resource><!-- 额外添加,将 src/main/java 下的所有 .xml 文件也视为资源 --><resource><directory>src/main/java</directory><includes><include>**/*.xml</include></includes></resource></resources>
</build>
配置解析
<directory>src/main/java</directory>
指定要扫描的目录为src/main/java。<includes><include>**/*.xml</include></includes>
仅复制此目录下所有.xml文件(递归子目录),其余.java文件不会被当作资源。src/main/resources配置还保留,方便项目其他配置文件(如application.properties、mybatis-config.xml等)也能被复制到target/classes。
当你执行 mvn clean package(或其他构建命令)后,Maven 就会:
- 编译
src/main/java下的.java文件生成.class放到target/classes - 同时 把
src/main/java下的.xml文件复制到target/classes
这样在运行阶段,所有 .xml 文件便存在于 classpath 下,MyBatis 即可加载它们。
四、验证与注意事项
-
查看编译输出
- 在执行
mvn clean package后,进入target/classes/com/xxx/dao/目录,确认能看到相应的.xml文件。如果没有,说明资源配置未生效或写法有误。
- 在执行
-
MyBatis 中的 Mapper 配置
-
需要在 mybatis-config.xml或者 SqlSessionFactoryBean 的 mapperLocations中指定正确的扫描路径:
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"><property name="dataSource" ref="personDataSource" /><property name="mapperLocations" value="classpath*:com/zxz/intelligenceCommand/dao/*.xml" />... </bean>或者在 mybatis-config.xml 中写:
<configuration><mappers><mapper resource="com/zxz/intelligenceCommand/dao/RoleDao.xml"/><mapper resource="com/zxz/intelligenceCommand/dao/UserDao.xml"/>...</mappers> </configuration> -
只要你保证编译后路径下有
RoleDao.xml等文件,MyBatis 就能找到。
-
-
避免与默认资源重复或冲突
- 如果你在
src/main/resources下也有同名.xml,可能会产生冲突或覆盖(除非你刻意这么做)。一般不建议同名重叠。
- 如果你在
-
项目结构最佳实践
- 虽然通过这种方式可以将
.xml文件和.java文件放在同一目录,但更常见或更推荐的做法是把 Mapper XML 放进src/main/resources/mapper之类的专门目录,使结构更清晰。
- 虽然通过这种方式可以将
五、总结
目标:在 src/main/java 与 .java 同一目录下的 .xml 文件也能编译进 classpath
方法:在 pom.xml 的 <build><resources> 中,额外增加一个 <resource> 配置项,指向 src/main/java 并用 <include>**/*.xml</include>,即可将对应的 XML 文件复制到 target/classes。
通过以上操作,可确保 MyBatis 在运行时正常加载这些 Mapper XML 文件,避免由于找不到映射而引发的 “Invalid bound statement (not found)” 等错误。
