【MyBatis新手避坑】详解 `Could not find resource ...Mapper.xml` 错误

文章目录

      • [一、 问题发现:当满屏红色指向一个"文件找不到"的错误](#一、 问题发现:当满屏红色指向一个“文件找不到”的错误)
      • [二、 为啥?深入理解 Maven/Gradle 的构建约定](#二、 为啥?深入理解 Maven/Gradle 的构建约定)
      • [三、 咋办?两种解决方案(强烈推荐第一种)](#三、 咋办?两种解决方案(强烈推荐第一种))
        • [方案一:【最佳实践】将 Mapper.xml 文件移至 `resources` 目录](#方案一:【最佳实践】将 Mapper.xml 文件移至 resources 目录)
        • [方案二:【备用方案】修改 `pom.xml` 配置文件](#方案二:【备用方案】修改 pom.xml 配置文件)
      • [四、 总结](#四、 总结)

如果你是一位正在学习 MyBatis 的 Java 开发者,那么你很可能在某个深夜,满怀期待地运行第一个测试时,被一盆红色的 ExceptionInInitializerError 冷水浇得透心凉。别灰心,这几乎是每个 MyBatis 新手的"成年礼"。今天,我们就来彻底解剖这个经典的错误,让你不仅知道"咋办",更明白"为啥"。

一、 问题发现:当满屏红色指向一个"文件找不到"的错误

让我们先回顾一下案发现场。你可能像我一样,精心编写了 StudentDao 接口、StudentMapper.xml 映射文件,以及一个用于获取 SqlSessionMyBatisUtils 工具类。然后,当你运行 StudentDaoTest 时,控制台却无情地打印出如下错误:

bash 复制代码
Exception in thread "main" java.lang.ExceptionInInitializerError
	at com.github.xxx.dao.StudentDaoTest.main(StudentDaoTest.java:16)
Caused by: org.apache.ibatis.exceptions.PersistenceException: 
### Error building SqlSession.
### The error may exist in com/github/xxx/dao/StudentMapper.xml
### Cause: org.apache.ibatis.builder.BuilderException: Error parsing SQL Mapper Configuration. Cause: java.io.IOException: Could not find resource com/github/xxx/dao/StudentMapper.xml
	...
Caused by: java.io.IOException: Could not find resource com/github/xxx/dao/StudentMapper.xml
	...

作为"侦探",我们应该学会从错误堆栈(Stack Trace)中寻找线索。拨开层层上报的异常迷雾,我们最终会定位到最根本的原因(Root Cause):

java.io.IOException: Could not find resource com/github/xxx/dao/StudentMapper.xml

这句话的潜台词非常直白:"嘿,我(MyBatis)找不到你让我加载的 StudentMapper.xml 这个文件!"

二、 为啥?深入理解 Maven/Gradle 的构建约定

要理解为什么会找不到,我们必须先了解 Java 项目构建工具(如 Maven 或 Gradle)的基本工作原理,这被称为"约定优于配置"(Convention over Configuration)。

在一个标准的 Maven 项目中,目录结构有着明确的约定:

  • src/main/java存放 Java 源代码(.java 文件) 。构建时,这个目录下的 .java 文件会被编译成 .class 文件,并输出到 target/classes 目录。
  • src/main/resources存放所有资源文件(非 .java 文件) 。例如 .xml, .properties 等。构建时,这个目录下的所有文件和目录结构会被原封不动地复制target/classes 目录。

那么,问题的根源就浮出水面了:

我们通常习惯于将 StudentMapper.xml 和它的接口 StudentDao.java 放在同一个包下,也就是 src/main/java/com/github/xxx/dao/。然而,根据 Maven 的默认约定,它只会编译 java 目录下的 .java 文件,而会忽略掉所有的 .xml 文件

最终导致的结果是,项目编译打包后,你的 target/classes 目录中只包含了 StudentDao.class,而 StudentMapper.xml 却"人间蒸发"了。当程序运行时,MyBatis 在 Classpath(也就是 target/classes)里自然找不到这个至关重要的 XML 文件,于是毫不犹豫地抛出了 IOException

三、 咋办?两种解决方案(强烈推荐第一种)

既然找到了病因,对症下药就变得非常简单了。

方案一:【最佳实践】将 Mapper.xml 文件移至 resources 目录

这是最符合 Maven 规范,也是业界通用的标准做法。它能确保你的项目结构清晰,职责分明。

  1. 定位 resources 目录 :在你的项目结构中,找到 src/main/resources

  2. 创建镜像目录 :在 resources 目录下,手动创建与你的 Dao 接口包名完全相同的目录结构。

    • 例如,如果你的 Dao 接口在 com.github.xxx.dao,那么就在 resources 下创建 com/github/xxx/dao
  3. 移动文件 :将 StudentMapper.xml 文件从 src/main/java/... 目录剪切并粘贴到新创建的 src/main/resources/com/github/xxx/dao/ 目录下。

最终,你的项目结构会是这样,清爽又规范:

复制代码
src
├── main
│   ├── java
│   │   └── com/github/xxx/dao
│   │       └── StudentDao.java          # 接口留在这里
│   │
│   └── resources
│       ├── com/github/xxx/dao
│       │   └── StudentMapper.xml      # XML文件移到这里
│       │
│       └── mybatis-config.xml         # 其他资源文件
│
└── test
  1. 重新运行 :现在,重新运行你的测试代码。Maven 会将 resources 下的所有内容 faithfully 复制到 target/classes,MyBatis 将顺利找到它的映射文件,错误也就随之消失。
方案二:【备用方案】修改 pom.xml 配置文件

如果你有强烈的个人偏好,坚持要将 .java.xml 文件放在一起,也不是不可以。你需要通过修改 pom.xml 文件来覆盖 Maven 的默认行为

  1. 打开项目根目录下的 pom.xml 文件。
  2. <build> 标签内,添加如下 <resources> 配置。这相当于告诉 Maven:"除了 resources 目录,也请把 java 目录下的 .xml 文件当作资源文件处理。"
xml 复制代码
<build>
    <resources>
        <!-- 处理 src/main/java 目录下的 XML 文件 -->
        <resource>
            <directory>src/main/java</directory>
            <includes>
                <include>**/*.xml</include>
            </includes>
            <filtering>false</filtering>
        </resource>
        <!-- 确保 src/main/resources 的默认行为不受影响 -->
        <resource>
            <directory>src/main/resources</directory>
            <includes>
                <include>**/*.xml</include>
                <include>**/*.properties</include>
            </includes>
            <filtering>true</filtering>
        </resource>
    </resources>
</build>
  1. 保存 pom.xml 文件,等待 IDE 刷新 Maven 配置后,再次运行即可。

虽然这种方法也能解决问题,但我个人不太推荐。因为它破坏了"约定优于配置"的原则,可能会让其他接手你项目的开发者感到困惑。

四、 总结

编程中的许多错误,看似是代码逻辑问题,实则是对工具链和底层原理理解不够深入。Could not find resource 这个错误就是最好的例子。

  • 病因 :Maven/Gradle 默认不打包 src/main/java 目录下的资源文件。
  • 药方 :遵循"约定优于配置"的原则,将资源文件(如 .xml)放置在 src/main/resources 目录下,并保持与 Java 包结构一致的目录结构。

希望这篇博客能帮助你彻底告别这个"新手村"的拦路虎。如果你觉得有帮助,欢迎点赞、收藏和分享!下次遇到问题,记得先从"为什么"开始思考,你会发现编程的世界会因此变得更加清晰。Happy Coding!

相关推荐
微笑伴你而行12 小时前
目标检测如何将同时有方形框和旋转框的json/xml标注转为txt格式
xml·目标检测·json
javadaydayup15 小时前
为什么 MyBatis Mapper 接口能像普通 Bean 一样被 @Autowired?
后端·mybatis
fatiaozhang952716 小时前
数码视讯TR100-OTT-G1_国科GK6323_安卓9_广东联通原机修改-TTL烧录包-可救砖
android·xml·电视盒子·刷机固件·机顶盒刷机
l1t17 小时前
美团龙猫利用expat库实现的保存xml指定范围数据到csv的C程序
xml·c语言·解析器·expat
大猫和小黄1 天前
IDEA终极配置指南:打造你的极速开发利器
intellij-idea
小趴菜不能喝1 天前
Spring boot3.x整合mybatis-plus踩坑记录
java·spring boot·mybatis
焯7592 天前
若依微服务遇到的配置问题
java·mybatis·ruoyi
l1t2 天前
DuckDB新版rusty_sheet 插件测试
xml·数据库·rust·插件·xlsx·duckdb
颜如玉2 天前
MybatisPlus Sql Inject魔法🪄
后端·mybatis·源码
zhong liu bin2 天前
maven【maven】技术详解
java·ide·python·spring·maven·intellij-idea