文档章节

Mybatis执行流程(二)

wjk_snail
 wjk_snail
发布于 2016/06/22 18:51
字数 617
阅读 57
收藏 1

码上生花,ECharts 作品展示赛正式启动!>>>

##获取MapperProxy ###执行流程图 ###源码走读

  //获取MapperProxy
  StudentDao userMapper = sqlSession.getMapper(StudentDao.class);
  //获取MapperProxy最终交给mapperRegistry代理
  public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
    return mapperRegistry.getMapper(type, sqlSession);
  }

  public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
    final MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory<T>) knownMappers.get(type);
    if (mapperProxyFactory == null)
      throw new BindingException("Type " + type + " is not known to the MapperRegistry.");
    try {
      //这里使用反射
      return mapperProxyFactory.newInstance(sqlSession);
    } catch (Exception e) {
      throw new BindingException("Error getting mapper instance. Cause: " + e, e);
    }
  }
  //反射获取
  protected T newInstance(MapperProxy<T> mapperProxy) {
    return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);
  }

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

##获取Excutor ###执行流程图 ###源码走读 ####invoke()

  //MapperProxy在执行时出发invoke()
   public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    if (Object.class.equals(method.getDeclaringClass())) {
      try {
        return method.invoke(this, args);
      } catch (Throwable t) {
        throw ExceptionUtil.unwrapThrowable(t);
      }
    }
    final MapperMethod mapperMethod = cachedMapperMethod(method);
    return mapperMethod.execute(sqlSession, args);
  }

  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;
  }

####execute()

//SimpleExecutor.execute()
 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 {
      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;
  }

####sqlSession一系列执行

  //在sqlSession一系列调用后转向Executor执行
  public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) {
    try {
      MappedStatement ms = configuration.getMappedStatement(statement);
      List<E> result = executor.query(ms, wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER);
      return result;
    } catch (Exception e) {
      throw ExceptionFactory.wrapException("Error querying database.  Cause: " + e, e);
    } finally {
      ErrorContext.instance().reset();
    }
  }

####Executor.query()执行

  public <E> List<E> query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException {
    //sql片段select * from student where id = ?
    BoundSql boundSql = ms.getBoundSql(parameterObject);
    CacheKey key = createCacheKey(ms, parameterObject, rowBounds, boundSql);
    //
    return query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
  }

  public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
    ErrorContext.instance().resource(ms.getResource()).activity("executing a query").object(ms.getId());
    if (closed) throw new ExecutorException("Executor was closed.");
    if (queryStack == 0 && ms.isFlushCacheRequired()) {
      clearLocalCache();
    }
    List<E> list;
    try {
      queryStack++;
      list = resultHandler == null ? (List<E>) localCache.getObject(key) : null;
      if (list != null) {
        handleLocallyCachedOutputParameters(ms, key, parameter, boundSql);
      } else {
        list = queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql);
      }
    } finally {
      queryStack--;
    }
    if (queryStack == 0) {
      for (DeferredLoad deferredLoad : deferredLoads) {
        deferredLoad.load();
      }
      deferredLoads.clear(); // issue #601
      if (configuration.getLocalCacheScope() == LocalCacheScope.STATEMENT) {
        clearLocalCache(); // issue #482
      }
    }
    return list;
  }

####SimpleExecutor.doQuery()

  //最终调用SimpleExecutor.doQuery()
  public <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
    Statement stmt = null;
    try {
      Configuration configuration = ms.getConfiguration();
      StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);
      stmt = prepareStatement(handler, ms.getStatementLog());
      return handler.<E>query(stmt, resultHandler);
    } finally {
      closeStatement(stmt);
    }
  }

####PreparedStatementHandler.query()

public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {
PreparedStatement ps = (PreparedStatement) statement;
ps.execute();
//返回结果集
return resultSetHandler.<E> handleResultSets(ps);
}

© 著作权归作者所有

wjk_snail
粉丝 8
博文 70
码字总数 50704
作品 0
东城
私信 提问
加载中
请先登录后再评论。
mybatis源码分析(二) 执行流程分析

mybatis源码分析(二) 执行流程分析 一丶环境准备   准备只使用mybatis的环境,去掉spring等框架,方便分析   mybatis从入门到精通(一) 入门 二丶从SqlSession#openSession()开始分析 //or...

osc_p0ka0957
2019/09/07
6
0
MyBatis初探一

一、MyBatis介绍 mybatis(持久层框架3.2.6 or 3.2.7)简单执行流程 >1.SqlMapConfig.xml(全局配置文件),配置数据源,事务和运行环境等 >2.配置映射文件(编写SQL语句):mapper.xml... >3.SqlSes...

AAASSSSddd
2016/04/02
160
0
mybatis 源码分析(一)框架结构概览

本篇博客将主要对 mybatis 整体介绍,包括 mybatis 的项目结构,执行的主要流程,初始化流程,API 等各模块进行简单的串联,让你能够对 mybatis 有一个整体的把握。另外在 mybatis 源码的阅读...

osc_qbe93woo
04/16
4
0
深入浅出MyBatis_Index

深入浅出MyBatis系列 【深入浅出MyBatis系列一】MyBatis入门 【深入浅出MyBatis系列二】配置简介(MyBatis源码篇) 【深入浅出MyBatis系列三】Mapper映射文件配置 【深入浅出MyBatis系列四】...

陶邦仁
2015/12/22
1.3K
0
Mybatis 创建Configuration对象

Mybatis 创建Configuration对象是在项目启动时就创建了。 具体创建流程为: https://blog.csdn.net/wolfcode_cn/article/details/80747923 MyBatis的本质是java对数据库的操作。 SqlSessonF...

osc_u90juso0
2018/07/19
2
0

没有更多内容

加载失败,请刷新页面

加载更多

nacos的启动方式以及注意的点

这个单机模式的启动方式 sh startup.sh -m standalone 注意,必须要加参数,如果不加参数启动了,无法正常访问 如果在用这个命令(sh startup.sh -m standalone)之前直接使用sh startup.sh ,...

千年典韦
7分钟前
5
0
奈学教你五分钟学会分布式事务

从概念开始 我们先从事务的定义开始。事务即一系列读存动作被当作一个执行单元,这些动作要么全成功,要么全失败,执行动作的过程中保证数据的隔离性和一致性。 我们抛离数据库这个特定场景,...

奈学教育
9分钟前
11
0
涨见识了,在终端执行 Python 代码的 6 种方式!

原作:BRETT CANNON 译者:豌豆花下猫@Python猫 英文:https://snarky.ca/the-many-ways-to-pass-code-to-python-from-the-terminal 为了我们推出的 VS Code 的 Python 插件 [1],我写了一个...

豌豆花下猫
20分钟前
12
0
查看未经删除的Git提交 - Viewing unpushed Git commits

问题: How can I view any local commits I've made, that haven't yet been pushed to the remote repository? 如何查看我所做的任何尚未推送到远程存储库的本地提交? Occasionally, git ......

javail
20分钟前
11
0
Markdown使用

Markdown语法 标题 标题使用#开头,然后再写文字,注意有#后有空格。 多个#表示不同字号的标题 字体设置 粗体:用****包裹的文字是粗体 斜体:用包裹的就是斜体* 加粗斜体:使用*包裹的就是加...

没天赋的演员
23分钟前
15
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部