前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >mybatis源码解析

mybatis源码解析

作者头像
爱撒谎的男孩
发布2019-12-31 16:30:36
4050
发布2019-12-31 16:30:36
举报
文章被收录于专栏:码猿技术专栏码猿技术专栏

文章目录

1. Configuration

2. MapperRegistry

3. MappedStatement

4. MapperProxyFactory

5. MapperProxy

6. MapperMethod

7. BoundSql

8. ResultHandler

9. TypeHandler

10. Mybatis四大关键类

10.1. Executor

10.2. ParameterHandler

10.3. ResultSetHandler

10.4. StatementHandler

11. 流程图

11.1. Mybatis创建MapperProxy

11.2. Mybaits执行查询

11.3. Mybaits执行查询的简化版

Configuration

  • mybatis的全局配置类,其中封装了mybatis的全部配置,在mybaits加载全局配置文件和Mapper文件的时候,会将里面的xml中的各个元素解析出来,封装在其中。
  • 主要的解析流程在org.apache.ibatis.builder.xml.XMLConfigBuilder#parseConfiguration有详细描述。
private void parseConfiguration(XNode root) {
    try {
      //issue #117 read properties first
      propertiesElement(root.evalNode("properties"));
      Properties settings = settingsAsProperties(root.evalNode("settings"));
      loadCustomVfs(settings);
      loadCustomLogImpl(settings);
      typeAliasesElement(root.evalNode("typeAliases"));
      pluginElement(root.evalNode("plugins"));
      objectFactoryElement(root.evalNode("objectFactory"));
      objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));
      reflectorFactoryElement(root.evalNode("reflectorFactory"));
      settingsElement(settings);
      // read it after objectFactory and objectWrapperFactory issue #631
      environmentsElement(root.evalNode("environments"));
      databaseIdProviderElement(root.evalNode("databaseIdProvider"));
      typeHandlerElement(root.evalNode("typeHandlers"));
      mapperElement(root.evalNode("mappers"));
    } catch (Exception e) {
      throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + e, e);
    }
  }

MapperRegistry

  • 其中存放了所有的Mapper信息,相当于Mapper的注册中心
  • 所有的Mapper信息都存放在Map<Class<?>, MapperProxyFactory<?>> knownMappers这个Map中,key是Mapper的全类名,value是MapperProxyFactory对象(用来创建代理对象)
  • 在mybaits加载配置文件解析Mapper的时候,会调用addMapper方法,将其添加到Map中。在获取Mapper的时候会调用getMapper方法,利用MapperProxyFactory对象创建一个代理对象返回。

MappedStatement

  • 封装了一个增删改查标签的全部属性,一个标签就是一个MappedStatement,保存在全局配置类中的Map<String, MappedStatement> mappedStatements

MapperProxyFactory

  • 创建Mapper代理对象的工厂类,其中最重要的两个方法如下:
//使用MapperProxy创建一个代理对象
protected T newInstance(MapperProxy<T> mapperProxy) {
    return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);
  }

  public T newInstance(SqlSession sqlSession) {
      //封装一个MapperProxy
    final MapperProxy<T> mapperProxy = new MapperProxy<>(sqlSession, mapperInterface, methodCache);
    return newInstance(mapperProxy);
  }

MapperProxy

  • Mapper的代理类,实现了InvocationHandler,当mapper调用方法的时候真正执行的方法是invoke
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    try {
      if (Object.class.equals(method.getDeclaringClass())) {
        return method.invoke(this, args);
      } else if (method.isDefault()) {
        return invokeDefaultMethod(proxy, method, args);
      }
    } catch (Throwable t) {
      throw ExceptionUtil.unwrapThrowable(t);
    }
    final MapperMethod mapperMethod = cachedMapperMethod(method);
    return mapperMethod.execute(sqlSession, args);
  }
  • 其中的属性有sqlSession(其中的属性有全局配置类Configuration)、mapperInterface(mapper真正的接口)、Map<Method, MapperMethod> methodCache

MapperMethod

  • 封装了Mapper接口中的单个方法,其中有两个重要的属性,如下:
    • SqlCommand:封装方法的全类名和执行的增删改查的类型(SqlCommandType的枚举类型)
    • MethodSignature:方法的签名,其中封装了该方法的一些信息,比如返回类型,返回值的类型等信息。
  • 其中有一个public Object execute(SqlSession sqlSession, Object[] args)方法,用来执行方法,如下:
    • 根据方法的不同类型,执行不同的逻辑
public 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;
  }

BoundSql

  • 封装了SQL语句的信息,包括需要执行的sql语句,参数列表等信息,通过MappedStatement中getBoundSql()方法创建。

ResultHandler

TypeHandler

Mybatis四大关键类

Executor

  • 执行器:在mybaits中负责执行增删改查和事务的操作,mybatis会根据不同的executorType创建不同的执行器
  • Mybaits的执行器主要有如下的类型:
    • ExecutorType.SIMPLE:这个执行器类型不做特殊的事情。它为每个语句的执行创建一个新的预处理语句。
    • ExecutorType.REUSE:这个执行器类型会复用预处理语句。
    • ExecutorType.BATCH:这个执行器会批量执行所有更新语句,如果 SELECT 在它们中间执行,必要时请把它们区分开来以保证行为的易读性。
  • 我们通过SqlSessionFactory创建sqlSession的时候可以传入执行器的类型,如果不传入,默认使用Simple类型的,在源码中的创建的执行的逻辑如下:
//org.apache.ibatis.session.Configuration#newExecutor(org.apache.ibatis.transaction.Transaction, org.apache.ibatis.session.ExecutorType)

public Executor newExecutor(Transaction transaction, ExecutorType executorType) {
    //如果没有指定,使用默认的类型
    executorType = executorType == null ? defaultExecutorType : executorType;
    executorType = executorType == null ? ExecutorType.SIMPLE : executorType;
    Executor executor;
    //批量执行的执行器
    if (ExecutorType.BATCH == executorType) {
      executor = new BatchExecutor(this, transaction);
    } else if (ExecutorType.REUSE == executorType) {
      executor = new ReuseExecutor(this, transaction);
    } else {
      executor = new SimpleExecutor(this, transaction);
    }
    //缓存执行器,实现二级缓存
    if (cacheEnabled) {
      executor = new CachingExecutor(executor);
    }
    executor = (Executor) interceptorChain.pluginAll(executor);
    return executor;
  }
  • 实现类型如下:
    • BatchExecutor:批量执行器
    • ReuseExecutor:复用执行器
    • SimpleExecutor:简单执行器,默认的
    • CachingExecutor:缓存执行器,mybaits中默认使用的执行器,用于二级缓存

ParameterHandler

  • 主要作用就是设置为Statement设置参数

ResultSetHandler

  • 主要作用就是对最后的结果进行处理

StatementHandler

  • 顾名思义就是创建JDBC中的Statement,实现类如下:
    • SimpleStatementHandler
    • PreparedStatementHandler
    • CallableStatementHandler
  • 主要的作用就是处理Statement,执行查询,对参数、查询结果进行处理。
  • 主要的方法如下:
    • Statement prepare(Connection connection, Integer transactionTimeout):创建Statement
    • void parameterize(Statement statement:设置参数
    • void batch(Statement statement):批量处理
    • <E> List<E> query(Statement statement, ResultHandler resultHandler):执行查询

流程图

  • 分析源码执行流程,画出对应的流程图,方便理解和记忆

Mybatis创建MapperProxy

  • 包括了读取全局配置文件和Mapper文件生成全局配置类、创建Mapper代理对象的详细过程

Mybaits执行查询

  • 主要描述了mybaits通过代理对象如何执行查询语句到对查询结果的处理过程的详细描述

Mybaits执行查询的简化版

  • 主要根据Mybatis中的重要的四大类,和SqlSession、TypeHandler进行简化描述,如下:
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019-08-05,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Configuration
  • MapperRegistry
  • MappedStatement
  • MapperProxyFactory
  • MapperProxy
  • MapperMethod
  • BoundSql
  • ResultHandler
  • TypeHandler
  • Mybatis四大关键类
    • Executor
      • ParameterHandler
        • ResultSetHandler
          • StatementHandler
          • 流程图
            • Mybatis创建MapperProxy
              • Mybaits执行查询
                • Mybaits执行查询的简化版
                相关产品与服务
                微服务引擎 TSE
                微服务引擎(Tencent Cloud Service Engine)提供开箱即用的云上全场景微服务解决方案。支持开源增强的云原生注册配置中心(Zookeeper、Nacos 和 Apollo),北极星网格(腾讯自研并开源的 PolarisMesh)、云原生 API 网关(Kong)以及微服务应用托管的弹性微服务平台。微服务引擎完全兼容开源版本的使用方式,在功能、可用性和可运维性等多个方面进行增强。
                领券
                问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档