1860 字
约 6 分钟
15
第06章 Mapper接口
无标签

第06章 Mapper接口

掌握 Mapper 接口的使用和接口映射机制
学习进度:24% 代码演示按钮 💻 查看完整代码 - 在线IDE体验

🎯 学习目标

📚

理解核心概念

掌握本章的核心概念和基本原理
🔧

掌握实践技能

学会相关的配置方法和实践技巧
💡

了解应用场景

明确在实际项目中的应用场景和最佳实践

学习目标

  • 深入理解MyBatis Mapper接口的概念和作用
  • 掌握XML映射和注解映射两种方式
  • 了解Mapper代理机制的工作原理
  • 学会定义和使用各种Mapper方法
  • 掌握参数传递和结果处理的技巧

Mapper接口概述

Mapper接口是MyBatis的核心组件,它定义了数据访问的方法签名,MyBatis会自动为这些接口创建代理实现,将方法调用转换为SQL执行。

Mapper接口的优势

  • 类型安全:编译时检查方法签名和参数类型
  • 代码简洁:无需编写实现类,只需定义接口
  • 易于维护:接口与SQL映射分离,便于管理
  • IDE支持:完整的代码提示和重构支持

XML映射方式

1. 定义Mapper接口

package com.example.mybatis.mapper;

import com.example.mybatis.model.User;
import org.apache.ibatis.annotations.Param;

import java.util.List;
import java.util.Map;

public interface UserMapper {
    
    // 查询所有用户
    List<User> selectAllUsers();
    
    // 根据ID查询用户
    User selectUserById(Long id);
    
    // 根据年龄查询用户
    List<User> selectUsersByAge(@Param("age") Integer age);
    
    // 条件查询
    List<User> selectUsersByCondition(Map<String, Object> params);
    
    // 统计用户数量
    long countUsers();
    
    // 插入用户
    int insertUser(User user);
    
    // 更新用户
    int updateUser(User user);
    
    // 删除用户
    int deleteUser(Long id);
}

2. 创建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.mybatis.mapper.UserMapper">
    
    <select id="selectAllUsers" resultType="User">
        SELECT id, name, age, email FROM users
    </select>
    
    <select id="selectUserById" parameterType="long" resultType="User">
        SELECT id, name, age, email FROM users WHERE id = #{id}
    </select>
    
    <select id="selectUsersByAge" parameterType="int" resultType="User">
        SELECT id, name, age, email FROM users WHERE age = #{age}
    </select>
    
    <select id="countUsers" resultType="long">
        SELECT COUNT(*) FROM users
    </select>
    
    <insert id="insertUser" parameterType="User" 
            useGeneratedKeys="true" keyProperty="id">
        INSERT INTO users (name, age, email) 
        VALUES (#{name}, #{age}, #{email})
    </insert>
    
    <update id="updateUser" parameterType="User">
        UPDATE users SET name = #{name}, age = #{age}, email = #{email} 
        WHERE id = #{id}
    </update>
    
    <delete id="deleteUser" parameterType="long">
        DELETE FROM users WHERE id = #{id}
    </delete>
    
</mapper>

3. 配置映射文件

<!-- 在mybatis-config.xml中配置 -->
<mappers>
    <mapper resource="mapper/UserMapper.xml"/>
</mappers>

注解映射方式

1. 基本注解

@Mapper
public interface UserAnnotationMapper {
    
    @Select("SELECT id, name, age, email FROM users")
    List<User> findAllUsers();
    
    @Select("SELECT id, name, age, email FROM users WHERE id = #{id}")
    User findUserById(@Param("id") Long id);
    
    @Insert("INSERT INTO users(name, age, email) VALUES(#{name}, #{age}, #{email})")
    @Options(useGeneratedKeys = true, keyProperty = "id")
    int insertUser(User user);
    
    @Update("UPDATE users SET name = #{name}, age = #{age}, email = #{email} WHERE id = #{id}")
    int updateUser(User user);
    
    @Delete("DELETE FROM users WHERE id = #{id}")
    int deleteUser(@Param("id") Long id);
    
    @Select("SELECT COUNT(*) FROM users")
    long countUsers();
}

2. 结果映射注解

@Select("SELECT id, name, age, email FROM users")
@Results({
    @Result(property = "id", column = "id"),
    @Result(property = "name", column = "name"),
    @Result(property = "age", column = "age"),
    @Result(property = "email", column = "email")
})
List<User> findAllUsersWithMapping();

3. 动态SQL注解

@SelectProvider(type = UserSqlProvider.class, method = "selectUsersByCondition")
List<User> findUsersByCondition(@Param("name") String name, @Param("minAge") Integer minAge);

// SQL提供者类
class UserSqlProvider {
    public String selectUsersByCondition(@Param("name") String name, @Param("minAge") Integer minAge) {
        StringBuilder sql = new StringBuilder("SELECT id, name, age, email FROM users WHERE 1=1");
        if (name != null && !name.isEmpty()) {
            sql.append(" AND name LIKE CONCAT('%', #{name}, '%')");
        }
        if (minAge != null) {
            sql.append(" AND age >= #{minAge}");
        }
        return sql.toString();
    }
}

Mapper代理机制

1. 代理对象的创建

// MyBatis自动创建代理对象
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);

// 查看代理对象信息
System.out.println("Mapper接口类型: " + userMapper.getClass().getName());
System.out.println("是否为代理对象: " + userMapper.getClass().getName().contains("Proxy"));

2. 方法调用流程

  1. 调用Mapper接口方法
  2. 代理对象拦截方法调用
  3. 根据方法名查找对应的SQL语句
  4. 执行SQL并处理结果
  5. 返回处理后的结果

参数传递

1. 单个参数

// 接口定义
User selectUserById(Long id);

// XML映射
<select id="selectUserById" parameterType="long" resultType="User">
    SELECT * FROM users WHERE id = #{id}
</select>

2. 多个参数(使用@Param)

// 接口定义
List<User> selectUsersByAgeRange(@Param("minAge") Integer minAge, 
                                 @Param("maxAge") Integer maxAge);

// XML映射
<select id="selectUsersByAgeRange" resultType="User">
    SELECT * FROM users WHERE age BETWEEN #{minAge} AND #{maxAge}
</select>

3. 对象参数

// 接口定义
int insertUser(User user);

// XML映射
<insert id="insertUser" parameterType="User">
    INSERT INTO users (name, age, email) 
    VALUES (#{name}, #{age}, #{email})
</insert>

4. Map参数

// 接口定义
List<User> selectUsersByCondition(Map<String, Object> params);

// XML映射
<select id="selectUsersByCondition" parameterType="map" resultType="User">
    SELECT * FROM users
    <where>
        <if test="name != null">
            AND name LIKE CONCAT('%', #{name}, '%')
        </if>
        <if test="minAge != null">
            AND age >= #{minAge}
        </if>
    </where>
</select>

返回值处理

1. 基本类型返回值

// 返回数量
long countUsers();

// 返回影响行数
int insertUser(User user);
int updateUser(User user);
int deleteUser(Long id);

2. 对象返回值

// 返回单个对象
User selectUserById(Long id);

// 返回对象列表
List<User> selectAllUsers();

3. Map返回值

// 返回Map
@MapKey("id")
Map<Long, User> selectUsersAsMap();

// 返回单行Map
Map<String, Object> selectUserAsMap(Long id);

最佳实践

1. 接口设计原则

  • 方法名要清晰表达业务意图
  • 参数类型要明确,避免使用Object
  • 返回值类型要准确,避免过度包装
  • 合理使用@Param注解标识参数

2. XML vs 注解选择

  • 简单SQL:使用注解,代码更简洁
  • 复杂SQL:使用XML,可读性更好
  • 动态SQL:推荐使用XML
  • 团队规范:保持一致的风格

3. 性能优化

  • 合理设计方法签名,避免不必要的数据传输
  • 使用合适的返回值类型
  • 避免在Mapper中进行复杂的业务逻辑
  • 合理使用批量操作方法

常见问题与解决方案

Q: Mapper接口方法找不到对应的SQL语句?

A: 检查namespace是否正确,方法名是否与SQL语句的id一致。

Q: 多个参数时出现参数绑定错误?

A: 使用@Param注解明确指定参数名称。

Q: 如何处理返回null的情况?

A: 在业务层进行null检查,或者使用Optional包装返回值。

Q: 注解和XML映射可以混合使用吗?

A: 可以,但建议在同一个项目中保持一致的风格。

实践练习

练习1:基本Mapper接口

创建一个完整的UserMapper接口,包含CRUD操作和统计方法。

练习2:注解映射

使用注解方式重新实现UserMapper的部分方法。

练习3:复杂参数传递

实现一个支持多条件查询的方法,使用Map传递参数。

练习4:批量操作

实现批量插入和批量删除的Mapper方法。

运行示例程序

步骤1:导入项目

将chapter-06-mapper-interface.json导入到IntelliJ IDEA中。

步骤2:配置数据库

确保MySQL数据库运行正常,执行init.sql创建测试数据。

步骤3:运行程序

运行MapperInterfaceDemo.java,观察不同映射方式的执行效果。

步骤4:查看结果

程序将演示XML映射器、注解映射器、Mapper方法和代理机制的使用。
本章小结

📖 本章小结

本章我们学习了 Mapper接口 的相关内容,包括:

  • 核心概念和基本原理
  • 配置方法和实践技巧
  • 应用场景和最佳实践
  • 常见问题和解决方案

下一章节 🎉

恭喜完成本章学习!

你已经掌握了 Mapper接口 的核心知识
第07章动态SQL继续学习 MyBatis 的更多特性和应用⏱️预计 30 分钟📊中等难度开始学习 → ← 第05章 📚 课程目录 第07章 →

第06章 Mapper接口
https://clxhxhhr.top/posts/3059/
作者
clxstart
发布于
2026-09-24
许可协议
CC BY-NC-SA 4.0
评论
0 条
还没有评论,先写一条吧。