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   }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM