zoukankan      html  css  js  c++  java
  • Mybatis源码分析:MapperMethod中内部静态类SqlCommand的作用

    MapperMethod中内部静态类SqlCommand的作用

       在MapperMethod初始化中,会首先初始化两个内部静态类,SqlCommand就是其中之一,SqlCommand的作用主要体现在MapperMethod类的execute()方法里,SqlCommand为其提供了查询类型和方法id两个信息,从而使用Sqlseesion执行不同的方法,那么SqlCommand是如何获取到查询类型和方法id的呢?其中又做了哪些操作呢?

      首先看看构造器中的代码执行顺序。构造器需要传入配置类,Mapper接口和Method类.

    1. 从Method类中获取方法名和该方法所在的类路径
    2. 根据mapper接口信息和配置类获取到XML对应的MapperStatement对象
    3. 判断映射语句对象是否为NULL,如果不为NULL,则从中获取到语句的id和待执行的Sql类型,如果为NULL,再次判断待执行方法上是否标注有Flush的注解,如果不满足条件,则会抛出BindingException异常。

      流程图如下所示:

         

    值得注意的是,在获取映射语句对象是通过调用resolveMappedStatement()方法实现的。见如下的讲述。

     1  public SqlCommand(Configuration configuration, Class<?> mapperInterface, Method method) {
     2      //获取方法名
     3         final String methodName = method.getName();
     4      //获取方法所在的类
     5         final Class<?> declaringClass = method.getDeclaringClass();
     6     //获取映射语句信息
     7       MappedStatement ms = resolveMappedStatement(mapperInterface, methodName, declaringClass,
     8           configuration);
     9       //如果映射语句对象是NULL,那么查看该方法上是否标注了FLUSH标签,如果存在,则设置查询类型为FLUSH,否则抛出BindingException异常表示接口找不到定义的方法。
    10       if (ms == null) {
    11         if (method.getAnnotation(Flush.class) != null) {
    12           name = null;
    13           type = SqlCommandType.FLUSH;
    14         } else {
    15           throw new BindingException("Invalid bound statement (not found): "
    16               + mapperInterface.getName() + "." + methodName);
    17         }
    18       }
    19       //如果映射语句对象不为空,则设置指定的查询类型,如果为UNKNOWN 类型,则直接抛出BindingException异常
    20       else {
    21         name = ms.getId();
    22         type = ms.getSqlCommandType();
    23         if (type == SqlCommandType.UNKNOWN) {
    24           throw new BindingException("Unknown execution method for: " + name);
    25         }
    26       }
    27     }

    resolveMappedStatement()方法

       该方法主要是获取映射语句对象,在xml配置中,像select,update,delete,insert 都需要提供id号和sql语句以及入参和出参信息,而MappedStatement就是xml到java对象的映射,一个<select//>标签就会对应一个MappedStatement对象,这个目前了解即可,在后续会专门进行介绍。现简要说明下代码的执行流程。

    1. 获取待执行语句的id号,id号形式为类路径.方法名

    2. 在配置类中是否能找到该语句的id号,如果能找到,则直接从配置类中返回MappedStatement实例,否则从父类接口中继续查找,如果找不到就返回NULL

    3. 如果入参接口路径就是方法所在的类路径,那么直接返回NULL

     1 private MappedStatement resolveMappedStatement(Class<?> mapperInterface, String methodName,
     2         Class<?> declaringClass, Configuration configuration) {
     3         //获取语句id 形式为接口名.方法名
     4       String statementId = mapperInterface.getName() + "." + methodName;
     5       //判断配置中是否存在该方法id
     6       if (configuration.hasStatement(statementId)) {
     7           //返回映射语句
     8         return configuration.getMappedStatement(statementId);
     9       }
    10       //如果接口信息就是所在类的话,直接返回NULL
    11       else if (mapperInterface.equals(declaringClass)) {
    12         return null;
    13       }
    14       //获取该类下的所有接口信息
    15       for (Class<?> superInterface : mapperInterface.getInterfaces()) {
    16           //从父接口中查找对应的方法ID,下列语句使用递归的方式进行查找
    17         if (declaringClass.isAssignableFrom(superInterface)) {
    18           MappedStatement ms = resolveMappedStatement(superInterface, methodName,
    19               declaringClass, configuration);
    20           if (ms != null) {
    21             return ms;
    22           }
    23         }
    24       }
    25       return null;
    26     }
    27   }
  • 相关阅读:
    EC中的QEvent
    Host是如何与EC通信的
    Python随笔之元组
    Vuex的基本使用
    运行新项目时先在项目目录下运行下面代码,安装依赖node_modules
    前端代码编辑时要注意大小写
    vue3.0的setup函数的使用
    angular写的一个导航栏
    Java数组的工具类
    eclipse格式化代码快捷键失效
  • 原文地址:https://www.cnblogs.com/zhengzuozhanglina/p/11221289.html
Copyright © 2011-2022 走看看