首页 > Java > java教程 > 正文

MyBatis 的Mapper接口是如何工作的?为什么没有实现类?

紅蓮之龍
发布: 2025-09-03 22:05:01
原创
488人浏览过
MyBatis通过动态代理自动生成Mapper接口实现类,运行时将接口方法绑定到SQL语句,结合XML映射文件中的SQL与参数配置,由SqlSession执行并返回结果,避免了手动编写实现类的繁琐过程。

mybatis 的mapper接口是如何工作的?为什么没有实现类?

MyBatis 的 Mapper 接口实际上并不需要我们手动去写实现类,它的工作方式有点像“魔法”,但背后是扎实的框架机制在支撑。简单来说,MyBatis 通过动态代理,在运行时生成接口的实现类,并将 SQL 语句绑定到这些实现类的方法上。

解决方案:

MyBatis 的 Mapper 接口工作流程主要依赖于以下几个核心机制:

  1. 接口定义: 首先,你需要定义一个 Mapper 接口,这个接口中的方法对应着你想要执行的 SQL 操作。接口方法可以接受参数,也可以返回结果。

    public interface UserMapper {
        User getUserById(int id);
        List<User> getAllUsers();
        void insertUser(User user);
        void updateUser(User user);
        void deleteUser(int id);
    }
    登录后复制
  2. SQL 映射文件: 然后,你需要创建一个 XML 映射文件,这个文件与 Mapper 接口对应,并且包含了 SQL 语句和接口方法之间的映射关系。

    <mapper namespace="com.example.UserMapper">
        <select id="getUserById" parameterType="int" resultType="com.example.User">
            SELECT * FROM users WHERE id = #{id}
        </select>
    
        <select id="getAllUsers" resultType="com.example.User">
            SELECT * FROM users
        </select>
    
        <insert id="insertUser" parameterType="com.example.User">
            INSERT INTO users (name, email) VALUES (#{name}, #{email})
        </insert>
    
        <update id="updateUser" parameterType="com.example.User">
            UPDATE users SET name = #{name}, email = #{email} WHERE id = #{id}
        </update>
    
        <delete id="deleteUser" parameterType="int">
            DELETE FROM users WHERE id = #{id}
        </delete>
    </mapper>
    登录后复制
  3. 动态代理: 当你通过

    SqlSession
    登录后复制
    获取 Mapper 接口的实例时,MyBatis 会使用 JDK 动态代理(或者 CGLIB,如果接口没有实现)创建一个代理对象。这个代理对象会拦截所有对接口方法的调用。

  4. 方法拦截和 SQL 执行: 当代理对象拦截到方法调用时,它会根据方法名和参数,在 XML 映射文件中查找对应的 SQL 语句。然后,它会使用

    SqlSession
    登录后复制
    执行 SQL 语句,并将结果映射到相应的 Java 对象。

  5. 结果返回: 最后,代理对象会将执行结果返回给调用者。

为什么没有实现类?因为 MyBatis 在运行时动态生成了实现类。 这避免了大量重复的样板代码,也使得代码更加简洁和易于维护。想象一下,如果每个 Mapper 接口都要手动写一个实现类,那将会是一场噩梦。

MyBatis 如何加载和解析 Mapper 映射文件?

MyBatis 通过

SqlSessionFactoryBuilder
登录后复制
构建
SqlSessionFactory
登录后复制
,在构建过程中,会解析 MyBatis 的配置文件 (mybatis-config.xml),其中会包含 Mapper 映射文件的位置。

具体来说,MyBatis 会使用

XMLConfigBuilder
登录后复制
解析配置文件,并使用
XMLMapperBuilder
登录后复制
解析 Mapper 映射文件。
XMLMapperBuilder
登录后复制
会读取 XML 文件,并将其中的 SQL 语句、参数映射、结果映射等信息解析成 MyBatis 内部的数据结构,例如
MappedStatement
登录后复制
。这些
MappedStatement
登录后复制
对象会被存储在
Configuration
登录后复制
对象中,供后续的 SQL 执行使用。

如果你的Mapper文件没有正确加载,可能会遇到

org.apache.ibatis.binding.BindingException: Invalid bound statement (not found)
登录后复制
错误。 检查你的 mybatis-config.xml 文件,确保Mapper文件路径正确,并且文件存在。 另外,检查Mapper接口的namespace是否和Mapper文件的namespace一致。

如何在 Spring Boot 中集成 MyBatis 并使用 Mapper 接口?

Spring Boot 提供了

mybatis-spring-boot-starter
登录后复制
依赖,可以方便地集成 MyBatis。

  1. 添加依赖: 首先,需要在

    pom.xml
    登录后复制
    文件中添加
    mybatis-spring-boot-starter
    登录后复制
    依赖。

    <dependency>
        <groupId>org.mybatis.spring.boot</groupId>
        <artifactId>mybatis-spring-boot-starter</artifactId>
        <version>2.2.0</version> <!-- 请使用最新版本 -->
    </dependency>
    登录后复制
  2. 配置数据源: 然后,需要在

    application.properties
    登录后复制
    application.yml
    登录后复制
    文件中配置数据源信息,例如数据库连接 URL、用户名、密码等。

    spring.datasource.url=jdbc:mysql://localhost:3306/mydatabase
    spring.datasource.username=root
    spring.datasource.password=password
    spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
    登录后复制
  3. 配置 MyBatis: 接下来,可以在

    application.properties
    登录后复制
    application.yml
    登录后复制
    文件中配置 MyBatis 的相关属性,例如 Mapper 接口的扫描路径、配置文件的位置等。

    mybatis.mapper-locations=classpath:mapper/*.xml
    mybatis.configuration.map-underscore-to-camel-case=true
    登录后复制
  4. 使用 Mapper 接口: 最后,可以使用

    @Autowired
    登录后复制
    注解将 Mapper 接口注入到你的 Service 或 Controller 中,并直接调用接口方法执行 SQL 操作。

    @Service
    public class UserService {
        @Autowired
        private UserMapper userMapper;
    
        public User getUserById(int id) {
            return userMapper.getUserById(id);
        }
    }
    登录后复制

注意, Spring Boot 会自动扫描 Mapper 接口,并将其注册为 Spring Bean。 如果你没有看到你的Mapper Bean被注入,检查你的启动类是否添加了

@MapperScan
登录后复制
注解,并指定正确的 Mapper 接口扫描路径。 例如:
@MapperScan("com.example.mapper")
登录后复制

MyBatis 的动态 SQL 是如何实现的?它有哪些常用的标签?

MyBatis 的动态 SQL 功能允许你根据不同的条件动态生成 SQL 语句,这在处理复杂的查询场景时非常有用。 动态 SQL 的实现依赖于 MyBatis 提供的各种标签,例如

<if>
登录后复制
,
<choose>
登录后复制
,
<when>
登录后复制
,
<otherwise>
登录后复制
,
<where>
登录后复制
,
<set>
登录后复制
,
<foreach>
登录后复制
等。

  • <if>
    登录后复制
    用于根据条件判断是否包含某段 SQL 片段。

    <select id="findActiveBlogWithTitleLike" resultType="Blog">
      SELECT * FROM blog
      WHERE state = ‘ACTIVE’
      <if test="title != null">
        AND title like #{title}
      </if>
    </select>
    登录后复制
  • <choose>
    登录后复制
    ,
    <when>
    登录后复制
    ,
    <otherwise>
    登录后复制
    类似于 Java 中的
    switch
    登录后复制
    语句,用于根据不同的条件选择不同的 SQL 片段。

    <select id="findActiveBlogLike" resultType="Blog">
      SELECT * FROM blog
      WHERE state = ‘ACTIVE’
      <choose>
        <when test="title != null">
          AND title like #{title}
        </when>
        <when test="author != null and author.name != null">
          AND author_name like #{author.name}
        </when>
        <otherwise>
          AND featured = 1
        </otherwise>
      </choose>
    </select>
    登录后复制
  • <where>
    登录后复制
    用于自动添加
    WHERE
    登录后复制
    关键字,并且可以智能地处理
    AND
    登录后复制
    OR
    登录后复制
    关键字的开头问题。

    <select id="findActiveBlogLike" resultType="Blog">
      SELECT * FROM blog
      <where>
        state = ‘ACTIVE’
        <if test="title != null">
          AND title like #{title}
        </if>
        <if test="author != null and author.name != null">
          AND author_name like #{author.name}
        </if>
      </where>
    </select>
    登录后复制
  • <set>
    登录后复制
    用于在
    UPDATE
    登录后复制
    语句中动态设置字段,并且可以智能地处理逗号的问题。

    <update id="updateAuthorIfNecessary">
      update Author
        <set>
          <if test="username != null">username=#{username},</if>
          <if test="password != null">password=#{password},</if>
          <if test="email != null">email=#{email},</if>
          bio=#{bio}
        </set>
      where id=#{id}
    </update>
    登录后复制
  • <foreach>
    登录后复制
    用于遍历集合,可以生成
    IN
    登录后复制
    语句或者批量插入语句。

    <select id="selectPostIn" resultType="Post">
      SELECT *
      FROM POST P
      WHERE ID in
      <foreach item="item" index="index" collection="list"
          open="(" separator="," close=")">
            #{item}
      </foreach>
    </select>
    登录后复制

在使用动态 SQL 时,需要注意 SQL 注入的风险。 尽量使用

#
登录后复制
占位符,而不是
${}
登录后复制
字符串替换。
#
登录后复制
占位符可以防止 SQL 注入,因为它会将参数值作为预编译语句的参数传递给数据库,而不是直接拼接到 SQL 语句中。

以上就是MyBatis 的Mapper接口是如何工作的?为什么没有实现类?的详细内容,更多请关注php中文网其它相关文章!

最佳 Windows 性能的顶级免费优化软件
最佳 Windows 性能的顶级免费优化软件

每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习
PHP中文网抖音号
发现有趣的

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号