当前位置: 首页 > article >正文

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> 配置:

<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中指定正确的扫描路径:

      <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 就能找到。

  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)” 等错误。


http://www.kler.cn/a/468998.html

相关文章:

  • 西门子200smart存储卡作用
  • JavaScript语言的编程范式
  • 22408操作系统期末速成/复习(考研0基础上手)
  • 嵌入式linux中socket控制与实现
  • 125个Docker的常用命令
  • 4进货+后台事务
  • SocraticLM: Exploring Socratic Personalized Teaching with Large Language Models
  • 党员学习交流平台
  • Ae 效果详解:放大
  • springboot565企业车辆管理系统设计与实现(论文+源码)_kaic
  • Flink系列知识讲解之:深入了解 Flink 的网络协议栈
  • python学opencv|读取图像(二十六)使用cv2.putText()绘制文字进阶-在图像上写文字
  • AI定义汽车/跨域融合/整车智能,汽车智能化2.0时代新机会来了
  • Spring Boot 3 配置大全系列 —— 如何配置用户的登录与认证?
  • (转)rabbitmq怎么保证消息不丢失?
  • CPU过剩是什么意思? 有什么对电脑的影响吗?如何确认CPU有没有过剩
  • 太速科技-688-基于 VM1302的双路100G光纤PCIe4.0X16加速计算卡
  • 【Linux】函数
  • Hypium纯血鸿蒙系统 HarmonyOS NEXT自动化测试框架
  • 生成式AI新星:DeepSeek-V3 与 GPT-4o 的对比分析
  • R shiny app | 网页应用 空格分隔的文本文件在线转csv
  • Go语言的数据类型
  • 实时数仓: Hudi 表管理、Flink 性能调优或治理工具脚本
  • 微电网运维:保障能源“小宇宙”稳定运行
  • 代码随想录 day 22 回溯算法 part01
  • 自动化立体库安全使用管理制度完整版