MyBatis-底层源码解析-(详细),用了这么多年分页PageHelper

/**

  • 解析 <mapper url
    /
    ErrorContext.instance().resource(url);
    InputStream inputStream = Resources.getUrlAsStream(url);
    XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, url, configuration.getSqlFragments());
    mapperParser.parse();
    } else if (resource == null && url == null && mapperClass != null) {
    /
    *
  • 解析 <mapper class
    /
    Class<?> mapperInterface = Resources.classForName(mapperClass);
    configuration.addMapper(mapperInterface);
    } else {
    /
    *
  • 以下代码可以看出 url resource class 三个属性只能选择一个,否则就会报错
    */
    throw new BuilderException(“A mapper element may only specify a url, resource or class, but not more than one.”);
    }
    }
    }
    }
    }
    }

1.4.2:mapperParser.parse();解析

我的UserMapper.xml文件内容为:

<?xml version="1.0" encoding="UTF-8"?> select * from `user` where userId = #{userId}

UserMapper接口内容为:

package com.mapper;

import com.entity.User;
import org.apache.ibatis.annotations.Select;

public interface UserMapper {
@Select(“select * from user where userId = 2”)
User findById(int userId);
}

疑问?UserMapper.xml有<select id=“findById”,而在接口中的findById方法我又加了一个@Select注解;那么执行会选择哪一条Sql执行还是报错呢?

以UserMapper.xml为例子解析,可以看到 resource = mapper/UserMapper.xml
在这里插入图片描述

public class XMLMapperBuilder extends BaseBuilder {
public void parse() {
if (!configuration.isResourceLoaded(resource)) {
/**

  • 解析 mapper.xml文件内容
    /
    configurationElement(parser.evalNode("/mapper"));
    configuration.addLoadedResource(resource);
    /
    *
  • 解析 mapper.xml的
  • namespace指定的{UserMapper}接口的注解信息
    */
    bindMapperForNamespace();
    }

parsePendingResultMaps();
parsePendingCacheRefs();
parsePendingStatements();
}
}

1.4.3:configurationElement(parser.evalNode("/mapper"));

解析 mapper.xml文件内容

public class XMLMapperBuilder extends BaseBuilder {
private void configurationElement(XNode context) {
try {
/**

  • namespace属性
    /
    String namespace = context.getStringAttribute(“namespace”);
    if (namespace == null || namespace.equals("")) {
    /
    *
  • 不指定 namespace会报错哦 由此得知 namespace属性是必须指定的
    /
    throw new BuilderException(“Mapper’s namespace cannot be empty”);
    }
    builderAssistant.setCurrentNamespace(namespace);
    /
    *
  • 解析 cache-ref
    /
    cacheRefElement(context.evalNode(“cache-ref”));
    /
    *
  • 解析 cache
    /
    cacheElement(context.evalNode(“cache”));
    /
    *
  • 解析 parameterMap
    /
    parameterMapElement(context.evalNodes("/mapper/parameterMap"));
    /
    *
  • 解析 resultMap
    /
    resultMapElements(context.evalNodes("/mapper/resultMap"));
    /
    *
  • 解析 sql
    /
    sqlElement(context.evalNodes("/mapper/sql"));
    /
    *
  • 解析 sql语句 select|insert|update|delete
  • 重点分析这里,这里的解析会关联到 mapper接口的执行方法 sql语句映射
    */
    buildStatementFromContext(context.evalNodes(“select|insert|update|delete”));
    } catch (Exception e) {
    throw new BuilderException(“Error parsing Mapper XML. The XML location is '” + resource + "’. Cause: " + e, e);
    }
    }
    }

1.4.4:buildStatementFromContext(context.evalNodes(“select|insert|update|delete”));

解析 sql语句 select|insert|update|delete;list参数内容是select|insert|update|delete的Sql语句
XMLStatementBuilder Sql语句的解析器
在这里插入图片描述

1.4.5:stateme

《一线大厂Java面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义》

【docs.qq.com/doc/DSmxTbFJ1cmN1R2dB】 完整内容开源分享

ntParser.parseStatementNode();解析Sql语句

builderAssistant.addMappedStatement,并不是添加一个mapper.xml文件隐射的实例,而是为每一个Sql语句创建一个实例

public class XMLStatementBuilder extends BaseBuilder {
private final MapperBuilderAssistant builderAssistant;
public void parseStatementNode() {
/**

  • 此处省略一大推代码…
    /
    /
    *
  • select * from user where userId = #{userId}
  • 参数解析
  • id:标签指定的id = findById
  • sqlSource:Sql语句,Sql参数占位
  • statementType:sql执行类型 参考{@link StatementType}
  •              STATEMENT: 直接操作sql,不进行预编译  ${}
    
  •              PREPARED: 预处理,参数,进行预编译    #{}
    
  •              CALLABLE: 执行存储过程
    
  • sqlCommandType:sql语句类型 参考{@link SqlCommandType}
  •              UNKNOWN:未知,INSERT:新增,UPDATE:修改,DELETE:删除,SELECT:查询,FLUSH:刷新
    
  • 其他参数可查看官网:https://mybatis.org/mybatis-3/zh/sqlmap-xml.html
    */
    builderAssistant.addMappedStatement(id, sqlSource, statementType, sqlCommandType,
    fetchSize, timeout, parameterMap, parameterTypeClass, resultMap, resultTypeClass,
    resultSetTypeEnum, flushCache, useCache, resultOrdered,
    keyGenerator, keyProperty, keyColumn, databaseId, langDriver, resultSets);
    }
    }

1.4.6:builderAssistant.addMappedStatement();

创建一个MappedStatement实例添加到 Configuration.mappedStatements的Map集合中

public class XMLStatementBuilder extends BaseBuilder {
public MappedStatement addMappedStatement() {
/**

  • 此处省略一大推代码…
    /
    MappedStatement.Builder statementBuilder = new MappedStatement.Builder(configuration, id, sqlSource, sqlCommandType)
    /
    *
  • 建造者模式
  • 用于设置 MappedStatement的属性
  • 此处省略一大推代码…
    */

/**

  • 设置参数入参类型 parameterType属性
  • select * from user where userId = #{userId}

*/
ParameterMap statementParameterMap = getStatementParameterMap(parameterMap, parameterType, id);
if (statementParameterMap != null) {
statementBuilder.parameterMap(statementParameterMap);
}

/**

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值