Mybaits 源码分析之Mapper参数解析

Mybaits 源码分析之Mapper参数解析

该文章是基于mybatis-spring-boot-starter讨论的,基于@MapperScan完成mapper加载,具体如何完成可参考其他文章,不在本篇文章的讨论范围内

涉及到的类

  • TokenHandler 处理token
  • GenericTokenParser 根据openToken,closeToken把token一个一个解析,并交由TokenHandler管理
  • SqlSource 存储sql语句以及SQL使用到的参数的对象
  • MappedStatement 映射的语句,存储SqlSource
  • Configuration.mappedStatements 映射语句集合,key是mapper命名空间+方法名

在这里插入图片描述

  • BoundSql mapper被执行时所需的所有参数SqlSource以及入参数据
    在这里插入图片描述

注意: token这里代表的是占位符号,例如(#{name}, ${name})

正文

Mybatis在初始化阶段就会根据@MapperScan找到所有mapper文件,并通过GenericTokenParser.parse()方法完成对占位符替换,将”#{age}“替换成”?“,这样可也让MySQL完成预编译缩短SQL执行时长,替换这个动作交由TokenHandler.handleToken完成,并通过parameterMappings存储变量与类型的映射关系,这个parameterMappings会在后续执行sql阶段将会用到,具体的实现类是(org.apache.ibatis.builder.SqlSourceBuilder.ParameterMappingTokenHandler)

当调用mapper方法时,mapper代理类通过Configuration.mappedStatements查找对应的MappedStatement,

Statement stmt = null;
try {
	Configuration configuration = ms.getConfiguration();
	StatementHandler handler = configuration.newStatementHandler(this, ms, parameter, RowBounds.DEFAULT, null, null); 			// 获取MappedStatement
	prepareStatement(handler, ms.getStatementLog());  	// 这里获取连接并且预编译sql并进行参数赋值
	handler.update(stmt); 								// 最终执行sql
} finally {
 	closeStatement(stmt);								// 释放资源
}

根据TypeHandle对预编译后的sql进行参数赋值

		  Object value;
          String propertyName = parameterMapping.getProperty();
          if (boundSql.hasAdditionalParameter(propertyName)) { // issue #448 ask first for additional params
            value = boundSql.getAdditionalParameter(propertyName);
          } else if (parameterObject == null) {
            value = null;
          } else if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {
            value = parameterObject;
          } else {
            MetaObject metaObject = configuration.newMetaObject(parameterObject);
            value = metaObject.getValue(propertyName);
          }
          TypeHandler typeHandler = parameterMapping.getTypeHandler();
          JdbcType jdbcType = parameterMapping.getJdbcType();
          if (value == null && jdbcType == null) {
            jdbcType = configuration.getJdbcTypeForNull();
          }
          try {
            typeHandler.setParameter(ps, i + 1, value, jdbcType);	// 这里最通过TypeHandler, 往PreparedStatement进行赋值
          } catch (TypeException | SQLException e) {
            throw new TypeException("Could not set parameters for mapping: " + parameterMapping + ". Cause: " + e, e);
          }

文章结束

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值