Mapper XML 文件纳入 classpath 的解决方案

文章目录

一、背景与问题描述

在使用 MyBatis 进行开发时,一般会将 Mapper 接口(.java) 存放于 src/main/java,而将对应的 Mapper XML(.xml) 存放于 src/main/resources 下,以便在 Maven 打包时,.xml 文件能够自动复制到 target/classes 目录,最终纳入 classpath 中。

如果因项目结构或其他原因,需要将 Mapper XMLMapper 接口 放置在同一目录(即 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


二、原理与思路

  1. Maven 资源(resources)机制
    • 默认情况下,Maven 会将 src/main/resources 目录下的所有文件拷贝到 target/classes,因此在运行或打包(jar/war)时,这些文件会处于 classpath 内。
    • src/main/java 目录下通常只放置 .java 文件进行编译,.xml.properties 等非 .java 文件不会自动复制到 target/classes
  2. 将特定目录或文件纳入资源
    • Maven 提供 <resources> 配置,让我们可以对任意目录 执行资源复制,也可以通过 <includes> / <excludes> 来筛选文件类型。
    • 只要在 <resources> 中添加一个 <resource> 块,指定 directory=src/main/javainclude=**/*.xml,就能让 .xml 文件也被复制到 target/classes
  3. MyBatis 加载 Mapper XML
    • MyBatis 需要在 classpath 中找到 Mapper XML 文件,无论是通过 mapperLocations=classpath*:**/*.xml 方式,还是在 mybatis-config.xml<mapper resource="..."> 方式,都依赖文件实际存在于 classpath
    • 因此,只有当 Maven 把 .xml 复制进 target/classes 后,MyBatis 才能在 classpath 中正确读取这些文件。

三、具体配置示例

在你的项目的 pom.xml 中,找到 <build> 节点,添加(或修改)如下 <resources> 配置:

xml 复制代码
<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>

配置解析

  1. <directory>src/main/java</directory>
    指定要扫描的目录为 src/main/java
  2. <includes><include>**/*.xml</include></includes>
    仅复制此目录下所有 .xml 文件(递归子目录),其余 .java 文件不会被当作资源。
  3. src/main/resources 配置还保留,方便项目其他配置文件(如 application.propertiesmybatis-config.xml 等)也能被复制到 target/classes

当你执行 mvn clean package(或其他构建命令)后,Maven 就会:

  • 编译 src/main/java 下的 .java 文件生成 .class 放到 target/classes
  • 同时src/main/java 下的 .xml 文件复制到 target/classes

这样在运行阶段 ,所有 .xml 文件便存在于 classpath 下,MyBatis 即可加载它们。


四、验证与注意事项

  1. 查看编译输出

    • 在执行 mvn clean package 后,进入 target/classes/com/xxx/dao/ 目录,确认能看到相应的 .xml 文件。如果没有,说明资源配置未生效或写法有误。
  2. MyBatis 中的 Mapper 配置

    • 需要在 mybatis-config.xml或者 SqlSessionFactoryBean 的 mapperLocations中指定正确的扫描路径:

      xml 复制代码
      <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 中写:

      xml 复制代码
      <configuration>
          <mappers>
              <mapper resource="com/zxz/intelligenceCommand/dao/RoleDao.xml"/>
              <mapper resource="com/zxz/intelligenceCommand/dao/UserDao.xml"/>
              ...
          </mappers>
      </configuration>
    • 只要你保证编译后路径下有 RoleDao.xml 等文件,MyBatis 就能找到。

  3. 避免与默认资源重复或冲突

    • 如果你在 src/main/resources 下也有同名 .xml,可能会产生冲突或覆盖(除非你刻意这么做)。一般不建议同名重叠。
  4. 项目结构最佳实践

    • 虽然通过这种方式可以将 .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)" 等错误。

相关推荐
小禾家的7 小时前
FastReport 加载Load(Stream) 模板内包含换行符不能展示
xml·开发语言
千千寰宇19 小时前
[车联网/计算机网络] Autosar 的 `ARXML` 配置数据库文件协议
xml·计算机网络·智能网联汽车-can总线协议·汽车/新能源汽车/智能网联汽车
雪芽蓝域zzs20 小时前
SpringBoot开发(六)SpringBoot整合MyBatis
spring boot·oracle·mybatis
Ase5gqe1 天前
【SpringBoot3】Spring Boot 3.0 集成 Mybatis Plus
spring boot·后端·mybatis
黎明晓月1 天前
MyBatis一条语句(PostgresSql)实现批量新增更新操作ON CONFLICT
java·postgresql·mybatis
飞翔的佩奇2 天前
Java项目: 基于SpringBoot+mybatis+maven+mysql实现的装饰工程管理系统(含源码+数据库+毕业论文)
java·数据库·spring boot·mybatis·ssm·毕设·装饰工程
安清h2 天前
【基于SprintBoot+Mybatis+Mysql】电脑商城项目之修改密码和个人资料
数据库·后端·mysql·spring·mybatis
LiuYuHani2 天前
Mybatis篇
java·开发语言·mybatis
xxxmine2 天前
Mybatis之常用动态Sql语句
数据库·sql·mybatis
黄晓琪2 天前
在MyBatis中,BoundSql对象的生成过程是怎样的?
java·spring·mybatis