MyBatis 核心知识点汇总
1. 前言
MyBatis 官网 Java-api 地址:https://mybatis.org/mybatis-3/zh/java-api.html
2. 常见配置
如果一个属性不止在一个地方进行配置,MyBatis 将按照以下顺序加载:
- 首先读取
properties元素体内的属性 - 然后根据
properties元素中的resource属性读取类路径下属性文件,或根据url属性指定的路径读取属性文件,并覆盖之前读取过的同名属性 - 最后读取作为方法参数传递的属性,并覆盖之前读取过的同名属性
优先级顺序:方法参数传递的属性 > resource/url 属性中配置 > properties 元素中指定属性
2.1 几个常见配置属性
| 设置名 | 描述 | 有效值 | 默认值 |
| cacheEnabled | 全局性地开启或关闭所有映射器配置文件中已配置的任何缓存 | true | false | true |
| lazyLoadingEnabled | 延迟加载的全局开关。开启时所有关联对象都会延迟加载,特定关联可通过 fetchType 覆盖 |
true | false | false |
| useGeneratedKeys | 允许 JDBC 支持自动生成主键(需数据库驱动支持),设置为 true 强制使用 | true | false | false |
| defaultExecutorType | 配置默认执行器:- SIMPLE:普通执行器- REUSE:重用预处理语句- BATCH:重用语句 + 批量更新 | SIMPLE、REUSE、BATCH | SIMPLE |
| localCacheScope | 本地缓存作用域:- SESSION:缓存会话中所有查询- STATEMENT:仅缓存当前语句 | SESSION、STATEMENT | SESSION |
| proxyFactory | 指定延迟加载对象的代理工具 | CGLIB | JAVASSIST | JAVASSIST(3.3 以上版本) |
2.2 多环境配置
多个数据源需创建多个 SqlSessionFactory,每个对应一个数据库。指定环境的方式:
- 向
SqlSessionFactoryBuilder传递环境参数 - 忽略环境参数则加载默认环境
environments 元素配置规则:
- 默认环境 ID:通过
default属性指定(如default="development") - 环境 ID:每个
environment元素的id属性(如id="development") - 事务管理器配置:
type属性(如type="JDBC") - 数据源配置:
type属性(如type="POOLED")
注意:环境名称可自定义,但默认环境 ID 必须匹配某个环境 ID。
2.3 事务管理
2.3.1 JDBC 事务管理
直接使用 JDBC 的提交 / 回滚机制,依赖数据源连接管理事务作用域。
2.3.2 MANAGED 事务管理
不主动提交 / 回滚连接,由容器(如 JEE 应用服务器)管理事务生命周期:
- 默认会关闭连接
- 若容器不希望关闭连接,需设置
closeConnection="false"
注意:Spring + MyBatis 集成时,无需配置事务管理器,Spring 会用自带管理器覆盖默认配置。两种事务管理器均无需额外设置属性。
3. XML (mapper) 关联映射
3.1 一对一映射
- 定义一对一
ResultMap,实现属性与字段的关联映射 - 若属性与字段名一致(含驼峰命名匹配,如
id对应USER_ID),可直接使用resultType resultMap主要用于解决字段与属性名不一致的场景
3.2 一对多映射(例:一个用户对应多个角色)
- 在
User类中添加List<Role>属性 - 在用户 mapper.xml 的
resultMap中添加<collection>标签
3.3 多对一映射(例:多个博客对应一个作者)
- 在
Blog类中添加Author属性 - 在博客 mapper.xml 的
resultMap中添加<association>标签
3.4 多对多映射(例:多个部门对应多个用户)
- 定义中间类(如
UserForDept.java),包含属性private User user; private Dept dept; User类中添加Set<Dept>(或List<Dept>),其 mapper.xml 中通过<collection>关联UserForDeptDept类中添加Set<User>(或List<User>),其 mapper.xml 中通过<collection>关联UserForDept
4. 分页实现
4.1 自带 RowBounds 分页
- 先查询全部结果集(ResultSet),再在内存中进行分页(limit)
- 属于逻辑分页
4.2 第三方插件 PageHelper
将查询 SQL 拆分为两步执行:
- 自动识别数据库类型,添加对应分页关键字(MySQL→limit、Oracle→rownum、DB2→fetch),查询分页结果
- 执行 count 语句,查询结果总条数
4.3 SQL 原生分页
依赖数据库原生语法实现,如 limit(MySQL)、rownum(Oracle)等。
4.4 数组分页
- DAO 层:定义查询全部数据的接口方法(如
List<Student> selectAll()) - Mapper.xml:编写查询全部数据的 SQL(无分页逻辑)
- Service 层:
- 定义分页方法(接收
currPage页码、pageSize每页条数) - 通过
List.subList()截取指定范围的数据
- Controller 层:接收前端参数,调用 Service 分页方法
4.5 拦截器分页
- 自定义拦截器,拦截指定规则的查询语句(如以 ByPage 结尾的方法)
- 统一在 SQL 后拼接分页语句(如 limit),实现分页逻辑
4.6 分页总结
| 分页类型 | 特点 | 适用场景 |
| 逻辑分页(RowBounds) | 内存开销大,小数据量效率高 | 数据量小的场景 |
| 物理分页(PageHelper、SQL、数组、拦截器) | 小数据量效率略低,无内存溢出风险 | 大数据量场景(推荐) |
优先级:物理分页 > 逻辑分页
5. 缓存
- 5.1 一级缓存
- 5.2 二级缓存
6. 执行器
6.1 SimpleExecutor
- 每执行一次 update/select,创建一个 Statement 对象
- 执行完成后立即关闭 Statement
6.2 ReuseExecutor
- 以 SQL 为 key 缓存 Statement 对象
- 存在则复用,不存在则创建
- 执行完成后不关闭,存入 Map 供下次使用
6.3 BatchExecutor
- 仅支持 update 操作(JDBC 批处理不支持 select)
- 将所有 SQL 加入批处理(addBatch ())
- 统一执行批处理操作(executeBatch ())
- 缓存多个 Statement 对象,等待批量执行