当前位置: 首页 > news >正文

MyBatis Mapper核心组件协作关系深度解析

本篇文章为本人之前所写的《深入浅出MyBatis:Mapper接口的工作原理与使用流程》的后续。

目录

前言

一、核心三角关系图解

二、组件职责与协作时序

1. MapperProxy - 动态代理的入口

2. MapperMethod - 方法执行引擎

3. MappedStatement - SQL操作蓝图

三、三组件协作流程图解

四、关键协作节点详解

五、设计思想:职责分离

1.MapperProxy - 门面层:

2.MapperMethod - 转换层

3.MappedStatement - 元数据层

总结


前言

        在之前我为大家介绍了Mapper接口的工作原理与使用流程,其中提到了三大核心组件协作,这次让我们聚焦MapperProxy、MapperMethod和MappedStatement这三个核心组件的协作逻辑,通过实际代码执行流程揭示它们的工作关系:


一、核心三角关系图解

二、组件职责与协作时序

1. MapperProxy - 动态代理的入口

核心职责:拦截所有Mapper接口方法调用,路由到MapperMethod

public class MapperProxy<T> implements InvocationHandler {public Object invoke(Object proxy, Method method, Object[] args) {// 1. 过滤Object原生方法if (Object.class.equals(method.getDeclaringClass())) {return method.invoke(this, args);}// 2. 创建或获取MapperMethod实例(缓存优化)MapperMethod mapperMethod = cachedMapperMethod(method);// 3. 将调用委托给MapperMethod执行return mapperMethod.execute(sqlSession, args);}
}
2. MapperMethod - 方法执行引擎

核心职责:将Java方法调用转化为具体的SQL操作指令

public class MapperMethod {// 两个关键子组件private final SqlCommand command;   // 关联SQL类型和IDprivate final MethodSignature method; // 方法签名元数据public Object execute(SqlSession sqlSession, Object[] args) {// 1. 获取MappedStatement(通过Configuration)MappedStatement ms = sqlSession.getConfiguration().getMappedStatement(command.getName());// 2. 根据SQL类型路由执行switch (command.getType()) {case SELECT:if (method.returnsVoid()) {executeWithResultHandler(sqlSession, args);} else if (method.returnsMany()) {return executeForMany(sqlSession, args);} else {return executeForObject(sqlSession, args);}case INSERT:return executeInsert(sqlSession, args);// UPDATE/DELETE 类似...}}private Object executeForMany(SqlSession sqlSession, Object[] args) {// 3. 参数转换Object param = method.convertArgsToSqlCommandParam(args);// 4. 执行SQL操作return sqlSession.selectList(command.getName(), param);}
}
3. MappedStatement - SQL操作蓝图

核心职责:存储SQL执行的完整元数据

public final class MappedStatement {private String id;  // 全限定方法名:com.example.UserMapper.selectByIdprivate SqlSource sqlSource;  // SQL脚本源码private SqlCommandType sqlCommandType; // SELECT/INSERT等// 结果映射配置private ResultMap resultMap;private List<ResultMap> resultMaps;// 参数映射配置private ParameterMap parameterMap;
}

三、三组件协作流程图解

四、关键协作节点详解

节点1:方法路由(MapperProxy → MapperMethod)
触发条件:任何Mapper接口方法调用

核心操作:

// 在MapperProxy中
if ("selectUser".equals(method.getName())) {// 创建处理select操作的MapperMethodreturn new MapperMethod(mapperInterface, method, sqlSession.getConfiguration()).execute(sqlSession, args);
}

节点2:SQL元数据绑定(MapperMethod → MappedStatement)
查找逻辑:

MappedStatement ms = configuration.getMappedStatement(mapperInterface.getName() + "." + method.getName()
);

元数据示例:

ms.getId()         // "com.example.UserMapper.selectUser"
ms.getSqlCommandType() // SqlCommandType.SELECT
ms.getResultMaps() // [UserResultMap]


节点3:参数转换与执行(MapperMethod → SqlSession)
参数处理

// 将Java参数转换为SQL可识别格式
Object param = method.convertArgsToSqlCommandParam(args);
// 示例:将@Param注解参数转为Map
// 输入:[101, "active"] → 输出:{"id":101, "status":"active"}

执行分发:

// 根据方法返回类型选择执行方式
if (method.returnsMany()) {return sqlSession.selectList(ms.getId(), param);
} else {return sqlSession.selectOne(ms.getId(), param);
}

五、设计思想:职责分离

1.MapperProxy - 门面层:

        负责接口层面的代理和路由

        隔离Java接口与执行逻辑

2.MapperMethod - 转换层

        桥接Java方法与SQL操作

        处理参数转换和结果映射决策

3.MappedStatement - 元数据层

        充当SQL操作的蓝图仓库

        解耦SQL定义与执行环境


总结

        这三个组件形成了MyBatis的执行链骨架。MapperProxy是入口,MapperMethod是转换引擎,MappedStatement是操作蓝图。它们通过严格的分层协作,将简单的Java方法调用转化为复杂的数据库操作,同时保持各层的独立性和可扩展性。这种设计使得MyBatis既能提供简洁的接口,又能处理复杂的SQL场景。

http://www.dtcms.com/a/324939.html

相关文章:

  • Java条件判断与用户交互实战案例
  • 【经典算法】二叉树最小深度详解:递归解法与可视化分析
  • 深入解析C#并行编程:从并行循环到异步编程模式
  • PyCATIA深度解析:基于装配截面自动化创建参考几何平面群的专业方案
  • 锂电生产设备健康管理:基于预测性维护的智能化解决方案​
  • 【github.io静态网页 怎么使用 github.io 搭建一个简单的网页?】
  • Python与MySQL数据库交互实践:自动化数据插入系统
  • GPU版的Pytorch安装(Win11)
  • SpringBoot项目自定义静态资源映射规则
  • 【嵌入式】Linux的常用操作命令 (1)
  • SAP 121移动类型的说明
  • C野指针的概念与应对(源头、阻隔、定位)
  • STM32定时器与延时系统完整笔记
  • 【C#补全计划】万类之父中的方法
  • 使用单调栈解决力扣第42题--接雨水
  • 亚麻云之静态资源管家——S3存储服务实战
  • SSH远程连接TRAE时显示权限被拒绝检查方案
  • 游泳学习 — 蛙泳
  • 变量详解:创建初始化与内存管理
  • go加速配置(下载第三方库)
  • go语言运算符
  • Java变量的声明规则与Scanner的应用
  • 算法训练营day44 动态规划⑪ 1143.最长公共子序列、1035.不相交的线、53. 最大子序和、392.判断子序列
  • BGP实验
  • (三)全栈(部署)
  • 数学建模——回归分析
  • 解决 Linux 下 “E: 仓库xxx没有数字签名” 问题
  • C++高频知识点(十九)
  • CentOS7.9 离线安装mysql数据库
  • Python vs MATLAB:智能体开发实战对比