1694 字
约 5 分钟
2
Mapper接口进阶
无标签

第19章 Mapper接口进阶

深入理解 Mapper 接口的高级特性和最佳实践 学习进度:76% 代码演示按钮 💻 查看完整代码 - 在线IDE体验

🎯 学习目标

📚

理解核心概念

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

掌握实践技能

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

了解应用场景

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

本章概述

Mapper接口是MyBatis的核心特性之一,它通过动态代理机制为开发者提供了类型安全、简洁优雅的数据访问方式。本章将深入探讨Mapper接口的工作原理、使用方法和最佳实践。

类型安全

编译时检查,避免运行时错误

代码简洁

无需编写实现类,专注业务逻辑

动态代理

运行时生成实现,灵活高效

注解支持

支持注解和XML两种配置方式

Mapper接口基础

什么是Mapper接口

Mapper接口是MyBatis中定义数据库操作方法的Java接口,通过动态代理机制自动生成实现类。

  • 定义数据库操作方法
  • 无需编写实现类
  • 支持注解和XML配置
  • 提供类型安全保障

动态代理原理

MyBatis使用JDK动态代理为Mapper接口生成代理对象,拦截方法调用并执行对应的SQL。

  • MapperProxyFactory创建代理
  • MapperProxy拦截方法调用
  • MapperMethod执行SQL
  • 结果自动映射返回

注解方式映射

@Mapper
public interface UserMapper {
    
    // 查询操作
    @Select("SELECT * FROM user WHERE id = #{id}")
    User selectById(Long id);
    
    // 插入操作
    @Insert("INSERT INTO user(username, email, age) VALUES(#{username}, #{email}, #{age})")
    @Options(useGeneratedKeys = true, keyProperty = "id")
    int insert(User user);
    
    // 更新操作
    @Update("UPDATE user SET username=#{username}, email=#{email}, age=#{age} WHERE id=#{id}")
    int update(User user);
    
    // 删除操作
    @Delete("DELETE FROM user WHERE id = #{id}")
    int deleteById(Long id);
}
@Results({
    @Result(property = "id", column = "user_id"),
    @Result(property = "username", column = "user_name"),
    @Result(property = "email", column = "user_email"),
    @Result(property = "age", column = "user_age")
})
@Select("SELECT user_id, user_name, user_email, user_age FROM user_info WHERE user_id = #{id}")
User selectFromUserInfo(Long id);

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">
    
    <!-- 结果映射 -->
    <resultMap id="userResultMap" type="com.example.mybatis.entity.User">
        <id property="id" column="id"/>
        <result property="username" column="username"/>
        <result property="email" column="email"/>
        <result property="age" column="age"/>
    </resultMap>
    
    <!-- 条件查询 -->
    <select id="selectByCondition" parameterType="map" resultMap="userResultMap">
        SELECT * FROM user
        <where>
            <if test="username != null and username != ''">
                AND username LIKE CONCAT('%', #{username}, '%')
            </if>
            <if test="minAge != null">
                AND age >= #{minAge}
            </if>
            <if test="maxAge != null">
                AND age <= #{maxAge}
            </if>
        </where>
        ORDER BY create_time DESC
    </select>
    
</mapper>

高级特性

批量操作分页查询动态SQLSQL构建器

批量操作

// 批量插入
@Insert("<script>" +
        "INSERT INTO user (username, email, age) VALUES " +
        "<foreach collection='users' item='user' separator=','>" +
        "(#{user.username}, #{user.email}, #{user.age})" +
        "</foreach>" +
        "</script>")
int batchInsert(@Param("users") List<User> users);

// 批量更新
@Update("<script>" +
        "<foreach collection='users' item='user' separator=';'>" +
        "UPDATE user SET username=#{user.username}, email=#{user.email} WHERE id=#{user.id}" +
        "</foreach>" +
        "</script>")
int batchUpdate(@Param("users") List<User> users);

分页查询

// 基本分页
@Select("SELECT * FROM user ORDER BY id LIMIT #{offset}, #{limit}")
List<User> selectByPage(@Param("offset") int offset, @Param("limit") int limit);

// 条件分页
@Select("<script>" +
        "SELECT * FROM user" +
        "<where>" +
        "<if test='username != null'>AND username LIKE CONCAT('%', #{username}, '%')</if>" +
        "<if test='minAge != null'>AND age >= #{minAge}</if>" +
        "</where>" +
        "ORDER BY id LIMIT #{offset}, #{limit}" +
        "</script>")
List<User> selectByConditionWithPage(@Param("username") String username,
                                    @Param("minAge") Integer minAge,
                                    @Param("offset") int offset,
                                    @Param("limit") int limit);

动态SQL

// 动态查询条件
@Select("<script>" +
        "SELECT * FROM user" +
        "<where>" +
        "<if test='id != null'>AND id = #{id}</if>" +
        "<if test='username != null and username != \"\"'>" +
        "AND username LIKE CONCAT('%', #{username}, '%')" +
        "</if>" +
        "<if test='email != null and email != \"\"'>AND email = #{email}</if>" +
        "<if test='minAge != null'>AND age >= #{minAge}</if>" +
        "<if test='maxAge != null'>AND age <= #{maxAge}</if>" +
        "</where>" +
        "ORDER BY create_time DESC" +
        "</script>")
List<User> selectByDynamicCondition(Map<String, Object> params);

SQL构建器

// SQL提供者类
public class UserSqlProvider {
    
    public String selectByCondition(Map<String, Object> params) {
        SQL sql = new SQL();
        sql.SELECT("*").FROM("user");
        
        if (params.get("username") != null) {
            sql.WHERE("username LIKE CONCAT('%', #{username}, '%')");
        }
        if (params.get("minAge") != null) {
            sql.WHERE("age >= #{minAge}");
        }
        if (params.get("maxAge") != null) {
            sql.WHERE("age <= #{maxAge}");
        }
        
        sql.ORDER_BY("create_time DESC");
        return sql.toString();
    }
}

// 使用SQL提供者
@SelectProvider(type = UserSqlProvider.class, method = "selectByCondition")
List<User> selectByCondition(Map<String, Object> params);

最佳实践

接口设计

  • 单一职责:每个Mapper接口只负责一个实体的数据操作
  • 方法命名:使用清晰、一致的方法命名规范
  • 参数设计:合理使用@Param注解,避免参数过多
  • 返回类型:根据业务需求选择合适的返回类型

SQL优化

  • 索引使用:确保查询条件字段有合适的索引
  • 分页查询:大数据量时使用LIMIT进行分页
  • 批量操作:使用批量插入/更新提高性能
  • 避免N+1:合理使用关联查询避免N+1问题

安全考虑

  • 参数校验:在Service层进行参数校验
  • SQL注入:使用#{}参数绑定防止SQL注入
  • 权限控制:在业务层实现数据权限控制
  • 敏感数据:避免在日志中输出敏感信息

配置管理

  • XML vs 注解:复杂SQL使用XML,简单SQL使用注解
  • 命名空间:确保Mapper XML的namespace与接口全限定名一致
  • 结果映射:复用ResultMap,避免重复定义
  • 缓存配置:合理配置二级缓存提高性能

实践练习

练习1:基础Mapper接口

目标

创建一个用户管理的Mapper接口,实现基本的CRUD操作。

要求

  • 使用注解方式定义基本的增删改查方法
  • 实现根据用户名模糊查询
  • 实现用户统计功能
  • 添加适当的参数校验

验证

编写测试类验证所有方法的正确性。

练习2:复杂查询实现

目标

使用XML方式实现复杂的动态查询功能。

要求

  • 实现多条件动态查询
  • 支持分页和排序
  • 实现批量操作
  • 使用ResultMap进行复杂结果映射

验证

测试各种查询条件组合的正确性。

练习3:性能优化

目标

优化Mapper接口的性能,提高查询效率。

要求

  • 分析SQL执行计划
  • 优化查询语句
  • 合理使用缓存
  • 实现批量处理

验证

对比优化前后的性能差异。

项目文件

本章小结

📖 本章小结

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

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

下一章节 🎉

恭喜完成本章学习!

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

Mapper接口进阶
http://www.clxhxhhr.top/posts/2861/
作者
clxstart
发布于
2026-09-19
许可协议
CC BY-NC-SA 4.0
评论
0 条
还没有评论,先写一条吧。