您的位置:首页 > 数据库

Mybatis源码分析:MapperMethod中内部静态类SqlCommand的作用

2019-07-21 15:14 555 查看
原文链接:http://www.cnblogs.com/zhengzuozhanglina/p/11221289.html

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   }

 

转载于:https://www.cnblogs.com/zhengzuozhanglina/p/11221289.html

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: