? ? 本文繼續(xù)沿用MyBatis系列 (1) ~ 啟動的demo挖胃,并在上文基礎(chǔ)上辽剧,說明MyBatis到底是如何執(zhí)行sql的族淮。MyBatis執(zhí)行一個查詢方法椭迎,可以分為兩步:Session的創(chuàng)建和結(jié)果的獲取彰阴。本文的內(nèi)容是基于demo特定代碼的結(jié)果瘾敢,如果你的配置文件或測試代碼不一致,結(jié)果可能不一樣。
一簇抵、Session的創(chuàng)建
? ? 1.如測試代碼所示【測試代碼和demo詳見MyBatis系列 (1) ~ 啟動】庆杜,調(diào)用ssf.openSession方法(圖1),將會返回一個session對象碟摆。而openSession()調(diào)用openSessionFromDataSource方法(圖2)晃财,在openSessionFromDataSource方法(圖3)中configuration.newExecutor會生成一個Executor實例(圖4),而這個Executor對象則是一個CachingExecutor實例典蜕,包裝了SimpleExecutor實例(圖5)拓劝,最后再利用Executor創(chuàng)建DefaultSqlSession實例并返回(圖3),至此session創(chuàng)建完成嘉裤。session對于sql的執(zhí)行郑临,都是利用executor去完成,可以說Executor是seeeion最重要的對象屑宠。
二厢洞、結(jié)果的獲取
? ? 這個過程大概會經(jīng)過MappedStatement查找、BoundSql的創(chuàng)建典奉、CacheKey的創(chuàng)建躺翻、緩存查找、JDBC操作(數(shù)據(jù)庫Connection建立卫玖、Statement建立公你、參數(shù)設(shè)置、結(jié)果處理)假瞬、緩存更新這幾個步奏陕靠。其中緩存的部分以后再分析。
? ? 1.MappedStatement查找脱茉。從Configuration對象的mappedStatements根據(jù)id獲取剪芥。mappedStatement如何添加到mappedStatements可以參照MyBatis系列 (1) ~ 啟動。
? ? ? ? 2.BoundSql的創(chuàng)建琴许。調(diào)用MappedStatement的getBoundSql方法會創(chuàng)建并返回一個BoundSql實例税肪。BoundSql會封裝好sql、參數(shù)榜田、類型益兄、typeHandler等信息,具體過程如下所示箭券。
? ? ? ? ? 3.CacheKey的創(chuàng)建净捅。調(diào)用CachingExecutor的createCacheKey方法會返回一個CacheKey對象實例。CacheKey根據(jù)MappedStatement的id邦鲫,偏移量灸叼,sql,參數(shù)庆捺,environment的id標(biāo)識古今。如果他們都相等,則可以判斷CacheKey也相等滔以。ddemo的CacheKey為"-1623403364:769426577:User.selectOneUser:0:2147483647:select t.id,t.name from user t where id = ?:2:development"捉腥。
? ? ? ? 4.JDBC操作。數(shù)據(jù)庫連接是在這里這里建立的你画,并不是一創(chuàng)建一個session實例就會建立一個連接抵碟。Connection由dataSource的doGetConnection方法返回。參數(shù)是由TypeHandler設(shè)置坏匪。
? ? ? ? 4.更新緩存拟逮。把相關(guān)結(jié)果存到localCache對象中,對于相同的CacheKey适滓,如果緩存中有值敦迄,則不需要到數(shù)據(jù)庫去查詢。
? ? ? ? 最后把結(jié)果返回給調(diào)用者凭迹,至此罚屋,MyBatis查詢執(zhí)行結(jié)束。