【2026】MyBatis 从入门到实战:一站式吃透持久层框架核心(附带核心知识点以及面试高频考点)

张开发
2026/4/9 17:44:46 15 分钟阅读

分享文章

【2026】MyBatis 从入门到实战:一站式吃透持久层框架核心(附带核心知识点以及面试高频考点)
前言在 Java 后端开发中数据库操作是绕不开的核心环节。传统 JDBC 编程存在代码冗余、硬编码严重、资源管理繁琐等问题而 MyBatis 作为一款优秀的半自动 ORM对象关系映射框架完美解决了这些痛点。它支持自定义 SQL、存储过程和高级映射将 SQL 与 Java 代码解耦是目前企业开发中主流的持久层框架之一。本文将从核心概念入手一步步讲解入门配置、核心语法、增删改查实战及核心配置解析帮助零基础同学快速掌握 MyBatis 的使用。一、MyBatis 核心认知1.1 什么是 MyBatisMyBatis原 iBatis是一款基于 Java 的半自动 ORM 框架它允许开发者专注于 SQL 编写同时自动完成 Java 对象与数据库记录的映射避免了 JDBC 中手动封装结果集、设置参数的重复工作。在分层架构中MyBatis 位于持久层DAO 层承接业务层Service的调用负责与数据库交互Controller控制层 → Service业务层 → MyBatis持久层 → 数据库1.2 JDBC vs MyBatis核心差异特性JDBCMyBatisSQL 管理硬编码在 Java 代码中维护困难独立配置在 XML / 注解中易维护参数设置手动设置占位符易出错自动映射参数支持多种参数类型结果集封装手动遍历 ResultSet 封装对象自动将结果映射为 Java 对象 / 集合资源管理手动关闭 Connection/Statement内置数据源和连接池自动管理资源SQL 注入风险需手动处理 PreparedStatement内置预编译机制天然防 SQL 注入代码冗余度高注册驱动、获取连接等重复低核心操作封装只需关注业务JDBC 代码示例痛点直观感受// 1. 注册驱动、获取连接硬编码 Class.forName(com.mysql.cj.jdbc.Driver); String url jdbc:mysql://localhost:3306/web?serverTimezoneAsia/Shanghai; Connection conn DriverManager.getConnection(url, root, 1234); // 2. 执行SQL、封装结果繁琐 String sql select * from user where username?; PreparedStatement ps conn.prepareStatement(sql); ps.setString(1, zhangsan); ResultSet rs ps.executeQuery(); ListUser userList new ArrayList(); while (rs.next()) { User user new User(); user.setId(rs.getInt(id)); user.setUsername(rs.getString(username)); userList.add(user); } // 3. 关闭资源资源浪费 rs.close(); ps.close(); conn.close();MyBatis 优化后代码// 仅需定义Mapper接口SQL在XML/注解中编写 UserMapper userMapper sqlSession.getMapper(UserMapper.class); User user userMapper.findByUsername(zhangsan);二、MyBatis 快速入门SpringBoot 整合版2.1 环境准备1创建 SpringBoot 工程通过 Spring Initializr 创建工程引入以下依赖MyBatis FrameworkMyBatis 核心依赖MySQL DriverMySQL 数据库驱动Lombok可选简化实体类代码2配置数据库连接在application.properties中配置数据库连接信息# 数据库连接配置 spring.datasource.urljdbc:mysql://localhost:3306/web?serverTimezoneAsia/Shanghai spring.datasource.driver-class-namecom.mysql.cj.jdbc.Driver spring.datasource.usernameroot spring.datasource.password1234 # MyBatis配置可选 mybatis.configuration.map-underscore-to-camel-casetrue # 自动映射下划线到驼峰命名2.2 第一个 MyBatis 案例查询用户步骤 1创建实体类POJOpackage com.example.mybatisdemo.pojo; import lombok.Data; Data // Lombok注解自动生成Getter/Setter/toString public class User { private Integer id; private String username; private String password; private String name; private Integer age; }步骤 2创建 Mapper 接口package com.example.mybatisdemo.mapper; import com.example.mybatisdemo.pojo.User; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Select; Mapper // 标记为MyBatis Mapper接口 public interface UserMapper { // 根据用户名查询用户 Select(select * from user where username #{username}) User findByUsername(String username); }步骤 3编写单元测试package com.example.mybatisdemo; import com.example.mybatisdemo.mapper.UserMapper; import com.example.mybatisdemo.pojo.User; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; SpringBootTest // 加载SpringBoot环境 public class MyBatisTest { Autowired private UserMapper userMapper; Test public void testFindByUsername() { User user userMapper.findByUsername(zhangsan); System.out.println(查询结果 user); } }✅注意测试类所在包需与启动类包名相同或在其子包下否则无法自动注入 Mapper。三、数据库连接池3.1 核心概念数据库连接池是一个容器负责分配、管理数据库连接Connection避免频繁创建 / 销毁连接导致的性能损耗核心优势资源复用连接可重复使用减少连接创建开销提升响应速度预先创建连接请求时直接获取统一管理可监控连接使用情况设置连接超时、最大连接数等3.2 标准接口与常见产品标准接口javax.sql.DataSource由 Sun 官方提供第三方实现常见产品C3P0老牌连接池稳定性高DBCPApache 开源性能中等Druid阿里巴巴开源功能强大支持监控、防 SQL 注入HikariCPSpringBoot 默认连接池性能最优3.3 SpringBoot 整合 Druid可选在pom.xml中引入 Druid 依赖dependency groupIdcom.alibaba/groupId artifactIddruid-spring-boot-starter/artifactId version1.2.18/version /dependency在application.properties中配置 Druidspring.datasource.typecom.alibaba.druid.pool.DruidDataSource # 连接池配置 spring.datasource.druid.initial-size5 spring.datasource.druid.max-active20 spring.datasource.druid.min-idle5四、MyBatis 核心操作增删改查CRUD实战4.1 新增操作INSERTMapper 接口Insert(insert into user(username, password, name, age) values (#{username}, #{password}, #{name}, #{age})) Options(useGeneratedKeys true, keyProperty id) // 获取自增主键并回填到实体类 int insertUser(User user);测试代码Test public void testInsertUser() { User user new User(); user.setUsername(lisi); user.setPassword(666666); user.setName(李四); user.setAge(22); int rows userMapper.insertUser(user); System.out.println(新增成功受影响行数 rows); System.out.println(新增用户ID user.getId()); // 自增主键已回填 }4.2 更新操作UPDATEMapper 接口Update(update user set name #{name}, age #{age} where id #{id}) int updateUser(User user);测试代码Test public void testUpdateUser() { User user new User(); user.setId(1); user.setName(张三_更新); user.setAge(25); int rows userMapper.updateUser(user); System.out.println(更新成功受影响行数 rows); }4.3 删除操作DELETEMapper 接口Delete(delete from user where id #{id}) int deleteUserById(Integer id);测试代码Test public void testDeleteUserById() { int rows userMapper.deleteUserById(1); System.out.println(删除成功受影响行数 rows); }4.4 查询操作SELECT多参数查询Param 注解当方法有多个参数时需用Param为参数命名Select(select * from user where username #{username} and password #{password}) User findByUsernameAndPassword(Param(username) String username, Param(password) String password);✅注意在 SpringBoot 官方骨架创建的项目中接口编译时会保留形参名Param注解可省略直接使用形参名。五、MyBatis 核心语法#{} vs ${}符号说明场景优缺点#{}占位符生成预编译 SQL参数值传递如where id #{id}安全、性能高推荐${}拼接符直接拼接 SQL 字符串动态设置表名 / 字段名如from ${tableName}不安全有 SQL 注入风险、性能低示例// 安全生成预编译SQL where id ? Delete(delete from user where id #{id}) // 动态表名直接拼接字符串需确保tableName可信 Select(select * from ${tableName} order by ${sortField})六、MyBatis XML 映射配置文件当 SQL 复杂或需要动态拼接时推荐使用 XML 映射文件核心规则同包同名XML 文件名与 Mapper 接口名一致且放置在相同包下namespace 绑定XML 的namespace属性为 Mapper 接口全限定名id 与方法名一致SQL 语句的id与接口方法名完全匹配6.1 配置示例Mapper 接口public interface UserMapper { ListUser findAll(); }XML 映射文件resources/mapper/UserMapper.xml?xml version1.0 encodingUTF-8? !DOCTYPE mapper PUBLIC -//mybatis.org//DTD Mapper 3.0//EN http://mybatis.org/dtd/mybatis-3-mapper.dtd mapper namespacecom.example.mybatisdemo.mapper.UserMapper select idfindAll resultTypecom.example.mybatisdemo.pojo.User select * from user /select /mapper6.2 动态 SQL常用标签if条件判断where自动处理多余的AND/ORforeach循环遍历如IN条件set动态更新字段示例多条件模糊查询xmlselect idfindByCondition resultTypecom.example.mybatisdemo.pojo.User select * from user where if testusername ! null and username ! and username like concat(%, #{username}, %) /if if testage ! null and age #{age} /if /where /selectMyBatis 核心知识点总结 面试高频考点对照表知识模块核心重点内容面试高频问题标准答案 / 答题要点MyBatis 基础认知1. 半自动 ORM 框架解耦 SQL 与 Java 代码2. 核心定位持久层框架替代 JDBC3. 优势减少代码冗余、自动映射结果、防 SQL 注入1. 什么是 MyBatis它是全自动 ORM 框架吗2. MyBatis 相比 JDBC 的优势有哪些1. MyBatis 是半自动 ORM 框架需手动编写 SQL自动完成 Java 对象与数据库记录的映射Hibernate 是全自动 ORM2. ① SQL 与代码解耦易维护② 自动封装结果集无需手动遍历 ResultSet③ 内置连接池管理资源④ #{ } 预编译防 SQL 注入JDBC vs MyBatis1. JDBC硬编码、手动管理资源、代码冗余2. MyBatisSQL 独立配置、自动映射、连接池管理、预编译1. 为什么说 MyBatis 能解决 JDBC 的痛点2. JDBC 编程有哪些缺点1. JDBC 痛点① SQL 硬编码在 Java 代码② 手动设置参数、封装结果③ 频繁创建 / 销毁连接性能差④ 需手动处理 SQL 注入2. MyBatis 通过 XML / 注解管理 SQL、自动映射结果、内置连接池、#{ } 预编译解决上述问题数据库连接池1. 核心作用资源复用、提升响应速度、统一管理连接2. 标准接口javax.sql.DataSource3. 常见产品HikariCPSpringBoot 默认、Druid、C3P04. 核心参数最大活跃连接数、最小空闲连接数1. 什么是数据库连接池作用是什么2. SpringBoot 默认的连接池是什么Druid 相比它有什么优势1. 连接池是管理数据库连接的容器预先创建连接请求时分配用完回收作用资源复用、提升性能、统一管理2. 默认 HikariCP性能最优Druid 优势支持监控、防 SQL 注入、多维度统计MyBatis 核心对象1.SqlSessionFactory全局唯一创建SqlSession通过SqlSessionFactoryBuilder构建2.SqlSession单次会话非线程安全执行 SQL、获取 Mapper 代理对象3.Mapper代理动态代理对象执行具体 SQL1. MyBatis 的核心对象有哪些生命周期是怎样的2.SqlSession是线程安全的吗为什么1. 核心对象SqlSessionFactoryBuilder方法级用完即丢→SqlSessionFactory应用级全局唯一→SqlSession请求级单次会话→Mapper代理方法级2. 非线程安全因为SqlSession包含连接对象多线程共享会导致连接混乱需每次请求创建新实例增删改查 - 新增1. 注解Insert2. XMLinsert标签3. 自增主键useGeneratedKeystrue keyPropertyid1. MyBatis 如何获取新增数据的自增主键2.useGeneratedKeys的作用是什么1. 两种方式① 注解Options(useGeneratedKeys true, keyProperty id)② XMLinsert useGeneratedKeystrue keyPropertyid主键会自动回填到实体类属性2. 开启获取自增主键功能keyProperty指定实体类中主键对应的属性名增删改查 - 更新 / 删除1. 注解Update/Delete2. XMLupdate/delete标签3. 注意事项必须加WHERE条件否则全表更新 / 删除1. MyBatis 执行更新操作时如何避免全表更新2. 删除操作的返回值是什么1. 编写 SQL 时必须添加WHERE条件指定更新 / 删除的范围MyBatis 不会自动添加条件2. 返回受影响的行数int 类型增删改查 - 查询1. 单条查询resultType指定返回对象类型2. 多条查询返回ListresultType指定泛型类型3. 多参数Param注解命名参数4. 结果映射ResultMap解决字段名与属性名不一致1. MyBatis 多参数传递有哪些方式2. 实体类属性名与数据库字段名不一致怎么办1. 三种方式①Param注解② 封装为实体类③ 使用 Map 集合2. 两种方案① 开启驼峰命名自动映射map-underscore-to-camel-casetrue② 自定义ResultMap手动映射XML 映射配置文件1. 核心标签mappernamespace 绑定接口、select/insert等2. 动态 SQLif/where/foreach/set3.#{} vs ${}#{}预编译防注入${}字符串拼接有风险1. MyBatis 中#{}和${}的区别是什么使用场景2. 动态 SQL 有哪些标签where标签的作用是什么1. 区别#{}是占位符生成?预编译防注入${}是拼接符直接拼接 SQL有注入风险场景#{}用于参数传递${}用于动态表名 / 字段名2. 动态 SQL 标签if/where/foreach/set等where作用自动拼接WHERE关键字移除多余的AND/ORMyBatis 缓存1. 一级缓存默认开启SqlSession级别同一SqlSession内查询相同数据只查一次数据库2. 二级缓存需手动开启namespace级别多个SqlSession共享1. MyBatis 的缓存机制是什么一级缓存和二级缓存的区别2. 如何开启二级缓存1. 一级缓存SqlSession级别默认开启关闭SqlSession缓存失效二级缓存namespace级别需手动开启缓存数据可跨SqlSession共享2. ① 全局配置开启缓存② 映射文件添加cache标签③ 实体类实现序列化接口面试高频考点补充核心原理MyBatis 的 Mapper 接口是如何生成代理对象的答MyBatis 使用动态代理技术当调用sqlSession.getMapper()时会通过MapperProxyFactory生成MapperProxy代理对象代理对象会拦截接口方法根据方法名和参数匹配 XML 中的 SQL 并执行。动态 SQLforeach标签的collection属性如何设置答根据参数类型设置参数是 List 时为list参数是 Array 时为array参数是 Map 时为 Map 的 key使用Param注解时为注解指定的名称。SpringBoot 整合 MyBatis核心步骤有哪些答① 引入 MyBatis 和 MySQL 驱动依赖② 配置数据库连接信息③ Mapper 接口添加Mapper注解或启动类添加MapperScan扫描④ 编写 SQL注解 / XML。七、总结与进阶方向7.1 核心知识点梳理MyBatis 定位半自动 ORM 框架专注 SQL 编写解耦 SQL 与 Java 代码核心对象SqlSessionFactory全局唯一→SqlSession单次请求→Mapper代理对象执行 SQL参数传递Param多参数、实体类复杂参数、Map灵活场景结果映射resultType名称一致、ResultMap名称不一致防 SQL 注入优先使用#{}占位符避免${}仅动态表名 / 字段名时使用7.2 进阶学习方向MyBatis 注解开发简化 XML适用于简单 SQL分页插件 PageHelper快速实现分页查询MyBatis 缓存一级缓存默认开启、二级缓存需手动配置动态 SQL 高级用法choose、trim、include等MyBatis-Plus增强版 MyBatis提供 CRUD 封装、代码生成等功能

更多文章