1694 字
约 5 分钟
2
Mapper接口进阶
2026-09-19
无标签
第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章 →
评论
0 条
还没有评论,先写一条吧。