mybatis的核心机制沉淀

沉底一下对传统技术栈,mybatis的认识

先讲个基本的点。

我们通过一个流程,对mybatis的企业开发中的常见流程。

1.引入依赖

2.在配置类,或者yaml中对mybatis做配置

3.创建mapper接口类,以及xml文件

4.在test中测试一下,写的接口写的有没有问题。

对于中间有很多细节只是点可以深挖

1.mybatis有哪些领域,是要在yaml,或者config文件包下做配置的。

2.动态sql

3.分页插件和逻辑

4.如何在mybatis中写复杂的sql

这些先不作为重点

我们研究一下mybatis下的原理层面,要认识的信息领域,

1.mybatis的执行原理是什么

2.对于mybatis的插件相关的知识

3.mybatis的缓存机制

4.mybatisd的连接池机制

5,mybatis有哪些机制可以实现分页,原理是什么


一、先讲基本点:MyBatis 企业开发标准流程

你列的 4 步完全正确,补充一个典型顺序:

1️⃣ 引入依赖(Spring Boot 场景)

xml 复制代码
<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>2.3.0</version>
</dependency>
<!-- 如果要用连接池监控,再加 Druid -->

2️⃣ 在 yaml 中做核心配置

yaml 复制代码
mybatis:
  mapper-locations: classpath:mapper/*.xml   # xml位置
  type-aliases-package: com.demo.entity      # 实体类短名
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
    map-underscore-to-camel-case: true       # 自动驼峰
    lazy-loading-enabled: true               # 延迟加载开关

3️⃣ 创建 Mapper 接口 + XML

java 复制代码
@Mapper
public interface UserMapper {
    User selectById(Long id);
}
xml 复制代码
<mapper namespace="com.demo.mapper.UserMapper">
    <select id="selectById" resultType="User">
        select * from user where id = #{id}
    </select>
</mapper>

4️⃣ 测试

java 复制代码
@SpringBootTest
class UserMapperTest {
    @Autowired UserMapper userMapper;
    @Test void test() {
        System.out.println(userMapper.selectById(1L));
    }
}

✅ 这是 99% 项目每天都在做的事


二、沉底:MyBatis 原理层 5 大核心领域

你现在真正想深挖的是这 5 个,我逐个给你讲"是什么 → 为什么 → 怎么实现"。


1️⃣ MyBatis 执行原理(最重要)

一句话

通过 动态代理 把 Mapper 接口和 SQL 绑定,通过 Executor + StatementHandler 执行 SQL 并映射结果。

核心流程(背下来):

复制代码
Mapper 接口
    ↓ 动态代理
MapperProxy
    ↓ 调用 MapperMethod
SqlSession → Executor → StatementHandler → ParameterHandler → ResultSetHandler

角色解释

组件 职责
MapperProxy 为你的 UserMapper 接口生成代理对象
MapperMethod 解析接口方法 → 找 XML 中的 SQL
SqlSession 对外提供增删改查 API
Executor 执行器(缓存、事务、批量)
StatementHandler 处理 JDBC Statement
ParameterHandler 设置参数
ResultSetHandler 把 ResultSet 映射成对象

一个 SQL 执行的真实路径

java 复制代码
userMapper.selectById(1)
  → MapperProxy.invoke()
  → MapperMethod.execute()
  → SqlSession.selectOne()
  → CachingExecutor.query()
  → SimpleExecutor.doQuery()
  → StatementHandler.query()
  → ResultSetHandler.handleResultSets()

👉 这是 MyBatis 源码阅读的入口线


2️⃣ MyBatis 插件原理(你已经接触过)

核心三要素

  • Interceptor:你写的插件逻辑
  • Invocation:当前执行方法的包装(目标、参数、方法)
  • Plugin:用 JDK 动态代理把多个拦截器串成责任链

最经典的插件

  • 分页插件(PageHelper)
  • 数据权限插件
  • 慢 SQL 监控插件

插件能拦截的四大对象

复制代码
Executor      → 执行器(分页、缓存)
StatementHandler → SQL 处理(改写 SQL)
ParameterHandler → 参数处理
ResultSetHandler → 结果处理(脱敏、加密)

👉 插件的本质是责任链 + 动态代理


3️⃣ MyBatis 缓存机制(一级缓存 + 二级缓存)

缓存级别 作用范围 是否默认开启 典型问题
一级缓存 SqlSession 内 ✅ 开启 同一个 Session 多次查询走缓存
二级缓存 Mapper 级别 ❌ 关闭 跨 Session 共享,易脏读

一级缓存(一定要懂)

java 复制代码
User u1 = mapper.selectById(1); // 查 DB
User u2 = mapper.selectById(1); // 走缓存
// 注意:执行 insert/update/delete 会清空缓存

二级缓存(谨慎开启)

xml 复制代码
<cache/>
  • 实体必须序列化
  • 多表查询时,一张表更新,另一张表缓存不会失效 → 脏数据

👉 真实生产:大部分项目只靠一级缓存 + Redis


4️⃣ MyBatis 连接池机制

关键点 :MyBatis 本身不实现连接池,而是包装 JDBC 的 DataSource

常见连接池:

  • HikariCP(Spring Boot 默认,最快)
  • Druid(功能最强,有监控)
  • Tomcat JDBC Pool

MyBatis 与连接池的关系

复制代码
MyBatis 配置 DataSource
    ↓
Spring 管理 Hikari/Druid
    ↓
MyBatis 每次执行 SQL 时:
  dataSource.getConnection()
  → 从连接池借连接
  → 执行 SQL
  → 归还连接

一个典型配置

yaml 复制代码
spring:
  datasource:
    hikari:
      maximum-pool-size: 20
      minimum-idle: 5

👉 MyBatis 只消费连接池,不生产连接池


5️⃣ MyBatis 分页机制(多种实现)

你问"有哪些机制可以实现分页",这是好问题:

分页方式 原理 优缺点
物理分页(推荐) 改写 SQL:limit ?,? 性能好,不走内存
逻辑分页(内存分页) 查全部数据,Java 中截取 性能极差,禁用
数组分页 同上 ❌ 不用于生产

物理分页的 3 种实现

1️⃣ PageHelper 插件(最常用)

java 复制代码
PageHelper.startPage(1, 10);
List<User> list = userMapper.selectAll();
PageInfo page = new PageInfo(list);

原理:拦截 Executor,改写 SQL 增加 limit

2️⃣ 手写 limit

xml 复制代码
<select id="selectPage">
  select * from user limit #{offset}, #{pageSize}
</select>

3️⃣ 分页拦截器自定义

  • 自己实现 Interceptor
  • 识别特定参数(如 PageParam
  • 动态改写 SQL

👉 结论:PageHelper 覆盖 90% 场景,手写 limit 适合极简项目。


三、你现在可以形成的"MyBatis 原理地图"

复制代码
用户调用 Mapper 接口
        ↓
【动态代理】MapperProxy
        ↓
【执行入口】SqlSession
        ↓
【拦截器链】Plugin(责任链)
        ↓
【核心执行】Executor(一级缓存在这里)
        ↓
【可选】二级缓存
        ↓
【SQL 处理】StatementHandler
        ↓
【参数】ParameterHandler
        ↓
【JDBC】getConnection(从连接池)
        ↓
【结果映射】ResultSetHandler

相关推荐
m0_380113844 小时前
补单系统搭建及源码分享
数据库·spring boot·mybatis
代码不加糖5 小时前
0基础搭建前后端分离项目:实现菜单与界面左右布局
java·前端·javascript·mysql·elementui·mybatis
Boop_wu6 小时前
[Java EE 进阶]Mybatis进阶(动态SQL)
java·数据库·maven·mybatis
xuhaoyu_cpp_java8 小时前
MyBatis学习(二)
java·经验分享·笔记·学习·mybatis
java1234_小锋8 小时前
MyBatis中XML映射有哪些标签?
xml·tomcat·mybatis
xuhaoyu_cpp_java12 小时前
MyBatis学习(一)
java·经验分享·笔记·学习·mybatis
happymaker062614 小时前
MyBatis学习日记——day01
学习·mybatis
君子剑mango14 小时前
mybatis plus逻辑删除
mybatis
wuqingshun3141592 天前
说说mybatis的缓存机制
java·缓存·mybatis