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

Mybatis源码阅读

作者头像
克虏伯
发布2019-05-19 16:45:47
3880
发布2019-05-19 16:45:47
举报

我们接着分析MapperMethod。如下List-1:

List-1

public class MapperMethod {

  private final SqlCommand command;
  private final MethodSignature method;

  public MapperMethod(Class<?> mapperInterface, Method method, Configuration config) {
    this.command = new SqlCommand(config, mapperInterface, method);
    this.method = new MethodSignature(config, mapperInterface, method);
  }

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

    List-1中,根据类型来调用不同的处理,我们以insert为例子分析,调用的就是如下的List-2,首先将传入Mapper方法上的参数转换为SQL参数,之后调用SqlSession的insert方法,注意这个SqlSession是SqlSessionTemplate,我们来看SqlSessionTemplate的insert方法,如List-3:

List-2

case INSERT: {
    Object param = method.convertArgsToSqlCommandParam(args);
    result = rowCountResult(sqlSession.insert(command.getName(), param));
    break;
}

List-3

public int insert(String statement, Object parameter) {
    return this.sqlSessionProxy.insert(statement, parameter);
}

如下图1所示,

                                                             图1

  •     步骤2调用的SqlSessionInterceptor是JDK的代理类;
  •     步骤4中,做了很多事情,比如不同类型Executor的生成就是在里面;
  •     步骤13中,会先清空缓存——因为我们目前看的是insert更新操作;
  •     步骤17中调用的StatementHandler默认是RoutingStatementHandler,用了Delegate设计模式,默认情况下委托给PreparedStatementHandler;
  •     步骤23中,涉及了KeyGenerator,所以后面看mybatis中返还主键值看这里;

    步骤17中,RoutingStatementHandler使用了代理模式,将事情全部委托给第三方来做。

    步骤1中调用的SqlSessionTemplate,以Template结尾,看着像使用Template模板模式,但是个人觉得是使用了代理模式,因为它内部实现上,大部分事情都委托给了内部类SqlSessionInterceptor。

    值得一提的是,BaseExecutor使用了Template模板模式,定义了执行步骤,然后具体实现由其实现类了实现。

    图1的过程中,涉及了事物,使用的是Spring的事物管理。

(adsbygoogle = window.adsbygoogle || []).push({});

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

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

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档