【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!

相关推荐
戴誉杰3 小时前
JAVA 程序员cursor 和idea 结合编程
java·ide·intellij-idea·cursor
XujiRe9 小时前
解决在IDEA、webstorm里Git特别慢的问题
git·intellij-idea·webstorm
helloworld工程师9 小时前
Dubbo应用开发之基于xml的第一个Dubbo程序
xml·dubbo·safari
bug攻城狮13 小时前
IDEA项目名称后面中括号的原因分析和解决方案
java·ide·后端·intellij-idea
Code季风17 小时前
Redis 缓存:应对缓存雪崩、缓存击穿和缓存穿透
数据库·redis·分布式·后端·缓存·微服务·mybatis
运维帮手大橙子1 天前
完整的登陆学生管理系统(配置数据库)
java·前端·数据库·eclipse·intellij-idea
JosieBook1 天前
【IDEA】IntelliJ IDEA 中文官方文档全面介绍与总结
java·ide·intellij-idea
2501_916766541 天前
【Mybatis入门】配置Mybatis(IDEA)
mybatis
Olrookie1 天前
若依前后端分离版学习笔记(七)—— Mybatis,分页,数据源的配置及使用
数据库·笔记·学习·mybatis·ruoyi