基于本文回答
0
评论

Mapper接口的绑定方式有哪几种?

知识点图片

本文介绍了MyBatis关联Mapper接口与SQL的四种核心绑定方式。从传统的XML手动配置(resource、class),到高效的包扫描(package、@MapperScan),对比了各自的优缺点,并强调了@MapperScan在现代Spring项目中的最佳实践地位。

MyBatis中,将Mapper接口和它的SQL语句(无论是定义在XML中还是注解中)关联起来的过程称为“绑定”(Binding)。MyBatis框架必须知道调用哪个接口方法时,应该去执行哪条SQL。

主要有以下几种绑定方式,从传统到现代,演进得越来越方便。


核心规则:命名空间(Namespace)

在讨论具体方式之前,必须先理解一个核心概念:XML映射文件中的namespace属性必须指向Mapper接口的全限定名。这是MyBatis能够将XML与接口关联起来的根本约定。

例如,如果你的接口是:

java
package com.example.mapper;

public interface UserMapper {
    User selectById(int id);
}

那么对应的XML文件头部必须是:

xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.mapper.UserMapper">
    <!-- SQL语句的id必须与接口方法名一致 -->
    <select id="selectById" resultType="com.example.model.User">
        select * from user where id = #{id}
    </select>
</mapper>

理解了这个基础约定后,我们再来看MyBatis是如何“发现”并加载这些Mapper的。


四种主要的Mapper绑定(扫描)方式

1. 通过XML的<mapper>标签,使用resource属性(最传统)

这是最原始、最明确的方式。你需要在MyBatis的核心配置文件 mybatis-config.xml 中,手动指定每一个Mapper XML文件的路径。

配置示例 (mybatis-config.xml):

xml
<configuration>
    ...
    <mappers>
        <mapper resource="mappers/UserMapper.xml"/>
        <mapper resource="mappers/OrderMapper.xml"/>
        <!-- 每增加一个新的Mapper,都需要在这里手动添加一行 -->
    </mappers>
</configuration>
  • 工作原理:MyBatis启动时,会读取这个配置文件,并根据resource属性指定的类路径(classpath)去加载对应的XML文件。
  • 优点:配置非常明确,一目了然。XML文件可以放在项目的任何位置,只要路径正确即可。
  • 缺点:非常繁琐。每当新增一个Mapper,都必须修改核心配置文件,容易遗漏,维护成本高。

2. 通过XML的<mapper>标签,使用class属性

这种方式是上一种的改进,它通过指定接口的类名来寻找映射文件。

配置示例 (mybatis-config.xml):

xml
<configuration>
    ...
    <mappers>
        <mapper class="com.example.mapper.UserMapper"/>
        <mapper class="com.example.mapper.OrderMapper"/>
    </mappers>
</configuration>
  • 工作原理:MyBatis会根据指定的接口全限定名,去寻找与之同名且在同一包路径下的XML文件。
    • 例如,对于 com.example.mapper.UserMapper,它会去类路径下寻找 com/example/mapper/UserMapper.xml 文件。
  • 优点:比resource方式更优,因为你不需要关心XML文件的具体物理路径,只需要保证它和接口在同一个包下即可。IDE构建工具(如Maven/Gradle)通常会默认将src/main/java下的Java文件和src/main/resources下的资源文件合并到同一个类路径下,所以这个约定很方便实现。
  • 缺点:仍然需要手动在配置文件中添加每一个Mapper接口,还是很繁琐。

3. 通过XML的<package>标签,进行包扫描(推荐的非Spring方式)

这是对前两种方式的巨大改进,从“逐个注册”变成了“批量扫描”。

配置示例 (mybatis-config.xml):

xml
<configuration>
    ...
    <mappers>
        <package name="com.example.mapper"/>
        <!-- 自动扫描该包下的所有Mapper接口 -->
    </mappers>
</configuration>
  • 工作原理:MyBatis会自动扫描com.example.mapper包及其子包下的所有接口,然后按照与方式二相同的规则(同名、同包)去查找并加载对应的XML映射文件。
  • 优点一劳永逸。一旦配置好包路径,后续在该包下新增任何Mapper接口,都无需再修改配置文件,MyBatis会自动发现它们。
  • 缺点:要求Mapper接口和XML文件必须遵循“同包同名”的约定。

4. 基于注解扫描(Spring/Spring Boot集成下的主流方式)

在与Spring或Spring Boot集成的环境下,我们通常不再使用mybatis-config.xml来配置mappers,而是使用注解来完成。

配置示例 (Spring Boot启动类或配置类):

java
@SpringBootApplication
@MapperScan("com.example.mapper") // 关键注解
public class MyApplication {
    public static void main(String[] args) {
        SpringApplication.run(MyApplication.class, args);
    }
}

或者在每个Mapper接口上单独标记:

java
@Mapper
public interface UserMapper {
    // ...
}
// 配合@ComponentScan,@Mapper本身是@Component
  • 工作原理
    • @MapperScan注解告诉MyBatis-Spring整合包去扫描指定的包,为找到的每一个接口生成代理对象,并将其注册为Spring Bean。
    • 如果接口上使用了SQL注解(如 @Select, @Insert 等),那么SQL就直接从注解中获取,甚至不需要XML文件。
    • 如果接口没有使用SQL注解,MyBatis会依然遵循与方式二相同的规则(同名、同包)去寻找并加载XML文件来获取SQL。
  • 优点
    • 完全融入了Spring的生态,配置简单,符合现代Java开发习惯。
    • 对于简单的SQL,可以直接写在注解里,省去XML文件,非常便捷。
    • 对于复杂的动态SQL,仍然可以继续使用XML文件,兼具灵活性。
  • 缺点:无明显缺点,是目前最主流、最推荐的使用方式。

总结与对比

绑定方式 配置位置 如何工作 优点 缺点 推荐场景
1. resource mybatis-config.xml 手动指定每个XML文件的路径 灵活,文件位置不限 极其繁琐,维护成本高 遗留项目或特殊文件布局
2. class mybatis-config.xml 手动指定每个接口的类名 无需硬编码路径 仍然繁琐,需要逐个添加 较少使用,是向包扫描的过渡
3. package mybatis-config.xml 指定包名,自动扫描 方便,一次配置,自动发现 需遵循"同包同名"约定 独立使用MyBatis(无Spring)
4. @MapperScan Spring配置类 注解指定包名,自动扫描 最方便,与Spring无缝集成,支持纯注解或XML混合 无明显缺点 Spring/Spring Boot项目(首选)

在现代的开发中,尤其是使用Spring Boot时,第四种方式(@MapperScan)是绝对的主流和最佳实践。它结合了注解的便利性和XML的强大功能,让开发效率和代码可维护性都达到了最佳平衡。

右滑查看面试常问