MyBatis原始碼解析 ---- MyBatis動態SQL底層原理分析
轉自 http://format-blog-image.qiniudn.com/dynamicsql2.png
前言
廢話不多說,直接進入文章。
我們在使用mybatis的時候,會在xml中編寫sql語句。
比如這段動態sql程式碼:
123456789101112131415 | < update id = "update" parameterType = "org.format.dynamicproxy.mybatis.bean.User" > UPDATE users < trim prefix = "SET" prefixOverrides = "," > < if test = "name != null and name != ''" > name = #{name} </ if > < if test = "age != null and age != ''" > , age = #{age} </ if > < if test = "birthday != null and birthday != ''" > , birthday = #{birthday} </ if > </ trim > where id = ${id} </ update > |
mybatis底層是如何構造這段sql的?
這方面的知識網上資料不多,於是就寫了這麼一篇文章。
下面帶著這個疑問,我們一步一步分析。
介紹MyBatis中一些關於動態SQL的介面和類
SqlNode介面,簡單理解就是xml中的每個標籤,比如上述sql的update,trim,if標籤:
123 | public interface SqlNode { boolean apply(DynamicContext context); } |
SqlSource Sql源介面,代表從xml檔案或註解對映的sql內容,主要就是用於建立BoundSql,有實現類DynamicSqlSource(動態Sql源),StaticSqlSource(靜態Sql源)等:
123 | public interface SqlSource { BoundSql getBoundSql(Object parameterObject); } |
BoundSql類,封裝mybatis最終產生sql的類,包括sql語句,引數,引數源資料等引數:
XNode,一個Dom API中的Node介面的擴充套件類。
BaseBuilder介面及其實現類(屬性,方法省略了,大家有興趣的自己看),這些Builder的作用就是用於構造sql:
下面我們簡單分析下其中4個Builder:
1 XMLConfigBuilder
解析mybatis中configLocation屬性中的全域性xml檔案,內部會使用XMLMapperBuilder解析各個xml檔案。
2 XMLMapperBuilder
遍歷mybatis中mapperLocations屬性中的xml檔案中每個節點的Builder,比如user.xml,內部會使用XMLStatementBuilder處理xml中的每個節點。
3 XMLStatementBuilder
解析xml檔案中各個節點,比如select,insert,update,delete節點,內部會使用XMLScriptBuilder處理節點的sql部分,遍歷產生的資料會丟到Configuration的mappedStatements中。
4 XMLScriptBuilder
解析xml中各個節點sql部分的Builder。
LanguageDriver介面及其實現類(屬性,方法省略了,大家有興趣的自己看),該介面主要的作用就是構造sql:
簡單分析下XMLLanguageDriver(處理xml中的sql,RawLanguageDriver處理靜態sql):
XMLLanguageDriver內部會使用XMLScriptBuilder解析xml中的sql部分。
ok, 大部分比較重要的類我們都已經介紹了,下面原始碼分析走起。
原始碼分析走起
Spring與Mybatis整合的時候需要配置SqlSessionFactoryBean,該配置會加入資料來源和mybatis xml配置檔案路徑等資訊:
12345 | < bean id = "sqlSessionFactory" class = "org.mybatis.spring.SqlSessionFactoryBean" > < property name = "dataSource" ref = "dataSource" /> < property name = "configLocation" value = "classpath:mybatisConfig.xml" /> < property name = "mapperLocations" value = "classpath*:org/format/dao/*.xml" /> </ bean > |
我們就分析這一段配置背後的細節:
SqlSessionFactoryBean實現了Spring的InitializingBean介面,InitializingBean介面的afterPropertiesSet方法中會呼叫buildSqlSessionFactory方法
buildSqlSessionFactory方法內部會使用XMLConfigBuilder解析屬性configLocation中配置的路徑,還會使用XMLMapperBuilder屬性解析mapperLocations屬性中的各個xml檔案。
部分原始碼如下:
由於XMLConfigBuilder內部也是使用XMLMapperBuilder,我們就看看XMLMapperBuilder的解析細節。
我們關注一下,增刪改查節點的解析。
XMLStatementBuilder的解析:
預設會使用XMLLanguageDriver建立SqlSource(Configuration建構函式中設定)。
XMLLanguageDriver建立SqlSource:
XMLScriptBuilder解析sql:
得到SqlSource之後,會放到Configuration中,有了SqlSource,就能拿BoundSql了,BoundSql可以得到最終的sql。
例項分析
我以以下xml的解析大概說下parseDynamicTags的解析過程:
123456789101112131415 | < update id = "update"
|