mybatis-spring 框架原理与源码解析--执行流程

上一篇文章https://blog.csdn.net/yange1025/article/details/84709273介绍了如何在Spring项目中配置mybatis以及mybatis的启动过程。本篇文章将从用户发起一笔查询到返回查询结果来介绍mybatis的执行流程。

入口从用户从Spring容器获取Mapper接口对应的bean,并调用接口方法执行查询开始。我们知道从Spring容器获取的Mapper bean是通过动态代理生成的,其所有方法的调用都会转嫁到MapperProxy的invoke方法

1 org.apache.ibatis.binding.MapperProxy#invoke

  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    try {
      // 如果是Object类中声明的方法,则直接反射调用该方法
      if (Object.class.equals(method.getDeclaringClass())) {
        return method.invoke(this, args);
      }
      // 如果是接口中的default方法,则通过Java动态语言支持MethodHandle调用
      else if (isDefaultMethod(method)) {
        return invokeDefaultMethod(proxy, method, args);
      }
    } catch (Throwable t) {
      throw ExceptionUtil.unwrapThrowable(t);
    }
    // 其他的是Mapper接口方法的实现
    final MapperMethod mapperMethod = cachedMapperMethod(method);
    return mapperMethod.execute(sqlSession, args);
  }

1.1 org.apache.ibatis.binding.MapperMethod#execute

  public Object execute(SqlSession sqlSession, Object[] args) {
    Object result;
    // command的name是mapper接口的方法名,如:com.my.UserMapper.retrieve
    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()) { // 返回Map
          result = executeForMap(sqlSession, args);
        } else if (method.returnsCursor()) { // 游标查询
          result = executeForCursor(sqlSession, args);
        } else { // 单条记录查询
          // 将方法参数转换成sql参数
          Object param = method.convertArgsToSqlCommandParam(args);
          // 调用sqlSession执行查询
          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
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值