MyBatis执行过程
创始人
2025-05-31 16:09:31
0

文章目录

  • 一、SpringBoot 集成MyBatis
    • 1. pom.xml添加依赖
    • 2.yml文件配置
    • 3.定义PO
    • 4. 定义mapper
    • 5.启动类
  • 二、sql执行过程
    • 1.加载mapper
    • 2.将UserMapper.selectUserById方法映射为Mapper.xml的sql
    • 3. SqlSessionTemplate拦截器SqlSessionInterceptor
    • 4. Mybatis的插件机制
    • 5. DefaultSelSession
    • 6. BaseExecutor
    • 7. SimpleExecutor
    • 8. newStatementHandler
    • 9.InterceptorChain
    • 10.PreparedStatementHandler
    • 11.PreparedStatement
    • 12.BaseExecutor#closeStatement
    • 13.SqlSesionUtils#closeSqlSession


一、SpringBoot 集成MyBatis

1. pom.xml添加依赖

org.springframework.bootspring-boot-starter-jdbcorg.springframework.bootspring-boot-starter-weborg.mybatis.spring.bootmybatis-spring-boot-starter2.3.0com.mysqlmysql-connector-jruntime

2.yml文件配置

server:port: 9994  #服务端口号logging:level:root: INFOspring:application:name: mybatis-test #提供者的服务名称--调用的时候根据改名称来调用对应服务的方法datasource:url: jdbc:mysql://127.0.0.1:3326/db?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghaidriver-class-name: com.mysql.cj.jdbc.Driverusername: rootpassword: rootmybatis:mapper-locations: classpath:mapper/*.xmltype-aliases-package: com.johar.mybatis.mybatistest.mapper

3.定义PO

public class Company {private Integer id;private String name;private String address;
}
public class User {private Integer id;private String name;private Integer age;private Integer sex;private Company company;
}

4. 定义mapper

public interface CompanyMapper {Company selectCompanyById(Integer id);
}
public interface UserMapper {User selectUserById(Integer id);
}








5.启动类

@SpringBootApplication
@MapperScan(basePackages = {"com.johar.mybatis.mybatistest.mapper"})
public class MybatisTestApplication {public static void main(String[] args) {SpringApplication.run(MybatisTestApplication.class, args);}}
@Service
public class UserService {@Autowiredprivate UserMapper userMapper;public User getById(Integer id){return userMapper.selectUserById(id);}}

二、sql执行过程

MyBatis作为常用的ORM框架之一,了解MyBatis中sql执行过程是应用开发必备的技能。如下图是MyBatis 的整体架构:
在这里插入图片描述
MyBatis的整体流程如下所示:
在这里插入图片描述
MyBatis的详细执行流程如下所示:
在这里插入图片描述

1.加载mapper

@MapperScan注解中默认的factoryBean是MapperFactoryBean,负责将CompanyMapper,UserMapper注入到Spring IOC。

@Overridepublic T getObject() throws Exception {return getSqlSession().getMapper(this.mapperInterface);}

最终调用的是MapperProxyFactory的newInstance,最终生成的是一个MapperProxy。

protected T newInstance(MapperProxy mapperProxy) {return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);}public T newInstance(SqlSession sqlSession) {final MapperProxy mapperProxy = new MapperProxy<>(sqlSession, mapperInterface, methodCache);return newInstance(mapperProxy);}

2.将UserMapper.selectUserById方法映射为Mapper.xml的sql

前面说到,Mapper实际上时一个MapperProxy的实例,因此调用selectUserById实际调用的是MapperProxy的invoke方法。

@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {try {if (Object.class.equals(method.getDeclaringClass())) {// Object的方法直接调用return method.invoke(this, args);} else {// 将mapper中方法映射为Mapper.xml的sqlreturn cachedInvoker(method).invoke(proxy, method, args, sqlSession);}} catch (Throwable t) {throw ExceptionUtil.unwrapThrowable(t);}}private MapperMethodInvoker cachedInvoker(Method method) throws Throwable {try {return MapUtil.computeIfAbsent(methodCache, method, m -> {if (m.isDefault()) {// 默认方法执行逻辑try {if (privateLookupInMethod == null) {return new DefaultMethodInvoker(getMethodHandleJava8(method));} else {return new DefaultMethodInvoker(getMethodHandleJava9(method));}} catch (IllegalAccessException | InstantiationException | InvocationTargetException| NoSuchMethodException e) {throw new RuntimeException(e);}} else {// 非默认方法执行逻辑return new PlainMethodInvoker(new MapperMethod(mapperInterface, method, sqlSession.getConfiguration()));}});} catch (RuntimeException re) {Throwable cause = re.getCause();throw cause == null ? re : cause;}}

接下来就是实际映射逻辑:

public MapperMethod(Class mapperInterface, Method method, Configuration config) {// 映射逻辑见其构造函数中调用的resolveMappedStatementthis.command = new SqlCommand(config, mapperInterface, method);this.method = new MethodSignature(config, mapperInterface, method);}// 实际执行的逻辑,将方法转换成sql:insert,update,delete,selectpublic Object execute(SqlSession sqlSession, Object[] args) {Object result;switch (command.getType()) {case INSERT: {Object param = method.convertArgsToSqlCommandParam(args);result = rowCountResult(sqlSession.insert(command.getName(), param));break;}case UPDATE: {Object param = method.convertArgsToSqlCommandParam(args);result = rowCountResult(sqlSession.update(command.getName(), param));break;}case DELETE: {Object param = method.convertArgsToSqlCommandParam(args);result = rowCountResult(sqlSession.delete(command.getName(), param));break;}case SELECT: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 if (method.returnsCursor()) {result = executeForCursor(sqlSession, args);} else {Object param = method.convertArgsToSqlCommandParam(args);result = sqlSession.selectOne(command.getName(), param);if (method.returnsOptional()&& (result == null || !method.getReturnType().equals(result.getClass()))) {result = Optional.ofNullable(result);}}break;case FLUSH:result = sqlSession.flushStatements();break;default: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;}
private MappedStatement resolveMappedStatement(Class mapperInterface, String methodName,Class declaringClass, Configuration configuration) {// 接口类名.方法名 作为唯一值,查询对应的sqlString statementId = mapperInterface.getName() + "." + methodName;if (configuration.hasStatement(statementId)) {return configuration.getMappedStatement(statementId);} else if (mapperInterface.equals(declaringClass)) {return null;}for (Class superInterface : mapperInterface.getInterfaces()) {if (declaringClass.isAssignableFrom(superInterface)) {MappedStatement ms = resolveMappedStatement(superInterface, methodName,declaringClass, configuration);if (ms != null) {return ms;}}}return null;}}

3. SqlSessionTemplate拦截器SqlSessionInterceptor

4. Mybatis的插件机制

5. DefaultSelSession

6. BaseExecutor

7. SimpleExecutor

8. newStatementHandler

9.InterceptorChain

10.PreparedStatementHandler

11.PreparedStatement

12.BaseExecutor#closeStatement

13.SqlSesionUtils#closeSqlSession

相关内容

热门资讯

富翁的近义词 富翁的近义词  近义词:  大亨、财主  大亨:大亨 dàhēng[magnate;big wig;...
背本就末的近义词 背本就末的近义词有:背本趋末,背本逐末,背本就末[bèi běn jiù mò]的意思:指背离根本,...
问牛知马的近义词 问牛知马的近义词有:举一反三,触类旁通,问羊知马,闻一知十,问牛知马[wèn niú zhī mǎ]...
不通文墨的近义词 不通文墨的近义词有:不识之无,胸无点墨,不通文墨[bù tōng wén mò]的意思:通:精通;文...
发奋图强是不是褒义词 发奋图强是不是褒义词  下定决心,努力追求进步。小编收集了发奋图强是不是褒义词,欢迎阅读。  典故出...
修辞立其诚的近义词 修辞立其诚的近义词有:修辞立诚,修辞立其诚[xiū cí lì qí chéng]的意思:诚:真心实...
屡试屡验的近义词 屡试屡验的近义词有:屡试不爽,屡试屡验[lǚ shì lǚ yàn]的意思:验:有效果。多次试验,都...
一通百通的近义词 一通百通的近义词有:畅通无阻,一通百通[yī tōng bǎi tōng]的意思:一个主要的弄通了;...
孤阴则不生,独阳则不长的近义... 孤阴则不生,独阳则不长的近义词有:孤阴不长,独阳不生,孤阴则不生,独阳则不长[gū yīn zé b...
见鞍思马的近义词 见鞍思马的近义词有:睹物思人,见鞍思马[jiàn ān sī mǎ]的意思:看见死去或离别的人留下的...
摇吻鼓舌的近义词 摇吻鼓舌的近义词有:摇唇鼓喙,摇唇鼓舌,摇吻鼓舌[yáo wěn gǔ shé]的意思:耍嘴皮,嚼舌...
手滑心慈的近义词 手滑心慈的近义词有:乐于助人,手滑心慈[shǒu huá xīn cí]的意思:慈:慈祥。手头慷慨,...
弓影浮杯的近义词 弓影浮杯的近义词有:杯弓蛇影,弓影浮杯[gōng yǐng fú bēi]的意思:形容疑神疑鬼,自相...
唯唯诺诺,唯唯诺诺的意思,唯... 唯唯诺诺wéi wéi nuò nuò [释义]形容自己没有主意;一味附和;恭顺听从的样子。[...
稀稀拉拉的近义词 稀稀拉拉的近义词有:三三两两,疏疏朗朗,稀稀落落,零零散散,稀稀拉拉[xī xī lā lā]的意思...
噬脐无及的近义词 噬脐无及的近义词有:噬脐何及,噬脐莫及,噬脐无及[shì qí wú jí]的意思:亦作“噬脐莫及”...
得意忘形的反义词   得意忘形  【反义词】怅然若失、心灰意冷  【注音】dé yì w&...
金鼓齐鸣的近义词 金鼓齐鸣的近义词有:刀光剑影,金鼓连天,金鼓齐鸣[jīn gǔ qí míng]的意思:金鼓:古时军...
疑惑的词语解释 关于疑惑的词语解释  【中文】:疑惑  【读音】:yí huò  【疑惑的意思】:心里不明白;困惑。...
乘虚以入的近义词 乘虚以入的近义词有:乘虚而入,乘虚以入[chéng xū yǐ rù]的意思:乘:趁着;虚:空隙,弱...