拼多多二面:Mybatis是如何执行一条SQL命令的?(1)

本文详细解释了ApacheMyBatis中的MapperMethod类,它负责解析Mapper接口的方法并将SQL命令映射到正确的SqlSession方法上。文章介绍了SqlCommand和MethodSignature的概念,展示了MapperMethod如何根据不同SQL类型执行插入、更新、删除、查询和刷新操作。
摘要由CSDN通过智能技术生成

// 缓存MapperMethod

private MapperMethod cachedMapperMethod(Method method) {

MapperMethod mapperMethod = methodCache.get(method);

if (mapperMethod == null) {

mapperMethod = new MapperMethod(mapperInterface, method, sqlSession.getConfiguration());

methodCache.put(method, mapperMethod);

}

return mapperMethod;

}

MapperMethod的功能:

  1. 解析Mapper接口的方法,并封装成MapperMethod对象。

  2. 将Sql命令,正确路由到恰当的SqlSession的方法上。

public class MapperMethod {

// 保存了Sql命令的类型和键id

private final SqlCommand command;

// 保存了Mapper接口方法的解析信息

private final MethodSignature method;

public MapperMethod(Class<?> mapperInterface, Method method, Configuration config) {

this.command = new SqlCommand(config, mapperInterface, method);

this.method = new MethodSignature(config, method);

}

// 根据解析结果,路由到恰当的SqlSession方法上

public Object execute(SqlSession sqlSession, Object[] args) {

Object result;

if (SqlCommandType.INSERT == command.getType()) {

Object param = method.convertArgsToSqlCommandParam(args);

result = rowCountResult(sqlSession.insert(command.getName(), param));

} else if (SqlCommandType.UPDATE == command.getType()) {

Object param = method.convertArgsToSqlCommandParam(args);

result = rowCountResult(sqlSession.update(command.getName(), param));

} else if (SqlCommandType.DELETE == command.getType()) {

Object param = method.convertArgsToSqlCommandParam(args);

result = rowCountResult(sqlSession.delete(command.getName(), param));

} else if (SqlCommandType.SELECT == command.getType()) {

if (method.returnsVoid() && method.hasResultHandler()) {

executeWithResultHandler(sqlSession, args);

result = null;

} else if (method.returnsMany()) {

result = executeForMany(sqlSession, args);

} else if (method.returnsMap()) {

result = executeForMap(sqlSession, args);

} else {

Object param = method.convertArgsToSqlCommandParam(args);

result = sqlSession.selectOne(command.getName(), param);

}

} else if (SqlCommandType.FLUSH == command.getType()) {

result = sqlSession.flushStatements();

} else {

throw new BindingException("Unknown execution method for: " + command.getName());

}

if (result == null && method.getReturnType().isPrimitive() && !method.returnsVoid()) {

throw new BindingException(“Mapper method '” + command.getName()

  • " attempted to return null from a method with a primitive return type (" + method.getReturnType() + “).”);

}

return result;

}

// …

org.apache.ibatis.binding.MapperMethod.SqlCommand。

public static class SqlCommand {

// full id, 通过它可以找到MappedStatement

private final String name;

private final SqlCommandType type;

// …

org.apache.ibatis.binding.MapperMethod.MethodSignature。

public static class MethodSignature {

private final boolean returnsMany;

private final boolean returnsMap;

private final boolean returnsVoid;

private final Class<?> returnType;

private final String mapKey;

private final Integer resultHandlerIndex;

private final Integer rowBoundsIndex;

private final SortedMap<Integer, String> params;

private final boolean hasNamedParameters;

public MethodSignature(Configuration configuration, Method method) {

this.returnType = method.getReturnType();

this.returnsVoid = void.class.equals(this.returnType);

this.returnsMany = (configuration.getObjectFactory().isCollection(this.returnType) || this.returnType.isArray());

this.mapKey = getMapKey(method);

this.returnsMap = (this.mapKey != null);

this.hasNamedParameters = hasNamedParams(method);

// 分页参数

this.rowBoundsIndex = getUniqueParamIndex(method, RowBounds.class);

// 自定义ResultHandler

this.resultHandlerIndex = getUniqueParamIndex(method, ResultHandler.class);

this.params = Collections.unmodifiableSortedMap(getParams(method, this.hasNamedParameters));

}

以上是对MapperMethod的补充说明。

本节的重点,是上面的那个Sql命令完整执行流程图。如果不是使用Mapper接口调用,而是直接调用SqlSession的方法,那么,流程图从SqlSession的地方开始即可,后续都是一样的。

读者福利


感谢你看到了这里!

我这边整理很多2020最新Java面试题(含答案)和Java学习笔记,如下图

在这里插入图片描述

上述的面试题答案小编都整理成文档笔记。 同时也还整理了一些面试资料&最新2020收集的一些大厂的面试真题(都整理成文档,小部分截图)免费分享给大家,有需要的可以 点击进入暗号:CSDN!免费分享~

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)

img

总结

我个人认为,如果你想靠着背面试题来获得心仪的offer,用癞蛤蟆想吃天鹅肉形容完全不过分。想必大家能感受到面试越来越难,想找到心仪的工作也是越来越难,高薪工作羡慕不来,却又对自己目前的薪资不太满意,工作几年甚至连一个应届生的薪资都比不上,终究是错付了,错付了自己没有去提升技术。

这些面试题分享给大家的目的,其实是希望大家通过大厂面试题分析自己的技术栈,给自己梳理一个更加明确的学习方向,当你准备好去面试大厂,你心里有底,大概知道面试官会问多广,多深,避免面试的时候一问三不知。

大家可以把Java基础,JVM,并发编程,MySQL,Redis,Spring,Spring cloud等等做一个知识总结以及延伸,再去进行操作,不然光记是学不会的,这里我也提供一些脑图分享给大家:

希望你看完这篇文章后,不要犹豫,抓紧学习,复习知识,准备在明年的金三银四拿到心仪的offer,加油,打工人!
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!
900569)]

[外链图片转存中…(img-bryTZIpB-1713702900569)]

[外链图片转存中…(img-R28nFi6Y-1713702900569)]

希望你看完这篇文章后,不要犹豫,抓紧学习,复习知识,准备在明年的金三银四拿到心仪的offer,加油,打工人!
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值