1. 程式人生 > >mybatis中的namespace及mapper

mybatis中的namespace及mapper

有時候遇到問題,我們可能在網上找不到解決方法,即使找得到也不要完全相信,我並不是說部落格內容有問題,我相信原創部落格比如經過作者的精心驗證,但是部落格不顧時間的肆意轉載,導致有些解決方案並不適合當前版本,我覺得作為一個程式設計師,要有嚴謹的工作態度,不能說哦原來這樣,讓應該問問自己咦,為什麼這樣。有時候自己看看原始碼或許也是解決問題的不錯途徑,今天我們從原始碼中分析下mybatis中的namespace到底該怎麼配置。 在mybatis的前身ibatis中namespace可以隨便寫,甚至可以不寫,他並沒有實際存在的意義,只是讓語句區分度更高了寫,一個淘汰的框架就不說他實現了。那麼在mybatis中namespace有何作用呢?Namespace實現語句與介面的繫結,通過生成mapper介面代理的方式替代dao層設計,當然如果不使用mapper介面的方式namespace依舊可以隨便寫,但不能不寫 如果要採用面向介面的程式設計方式,namespace必須為mapper介面的全類名物件。 為什麼這麼說呢?我們從原始碼的角度研究下,mybatis框架環環相扣,我們今天不討論每一步實現細節,只關注namespace相關。首先記住一點獲取代理物件必然要呼叫configuration.java中的getMapper方法。 在這裡插入圖片描述

在這裡插入圖片描述 因此使用之前,必然要註冊對映器,即先呼叫addMapper。 先看下mybatis對於配置檔案的解析,以config.xml為例,由SqlSessionFactoryBuilder類中build進入,真正對於xml檔案解析在XMLConfigBuilder中parseConfiguration,眾所周知mybatis中對映檔案的配置是通過config.xml的元素配置,此元素非必需,因為mybatis提供了註解的方式,同時再呼叫addMapper時會嘗試解析,容下問分解。 在這裡插入圖片描述 只關注mapperElement方法。

在這裡插入圖片描述 Mappers的配置有四種形式。 1.以方式配置 2.以方式配置,分別可以通過四種屬性配置。 如果是package方式,此時突然發現這個方法沒有解析對映檔案的邏輯,直接呼叫了addMappers,看看這個方法最終呼叫呼叫了addMapper. 在這裡插入圖片描述

回過頭來看看addMapper方法。 在這裡插入圖片描述 首先註冊了一個對映器,即將我們mapepr介面的型別與代理物件工廠繫結。然後看下面處理,從註釋也可以看得出來要生成mapepr代理物件需完成兩個過程,對映(不一定是檔案哦)解析,介面對映器的注入。 在這裡插入圖片描述 在這裡插入圖片描述 loadXmlResource作用是解析mapper對映檔案,什麼時候解析呢?在之前沒有解析過的時候進行解析,mybatis通過一個set列表標識解析資源。沒有解析過時通過mapper介面的全類名查詢資源,解析過的物件以三種不同的方式標識同一資源。因此此時決定了mapper介面與對映檔案必須完成相同(同名同包)。同時構造mapper.xml解析XMLMapperBuilder類物件,同時設定當前namespace為mapper介面全類名。 在這裡插入圖片描述
Mapper標籤解析如下: 在這裡插入圖片描述

開始獲取了namespace屬性,然後設定當前namespace,設定邏輯如下 在這裡插入圖片描述 由於當前namespace已經設定為mapper介面全名類,因為與對映檔案namespace不相同必然報錯,換句話說namespace必須為mapper介面全類名。 再看下一個方法,上面我們知道namespace即為namespace屬性值也就是mapper全類名,獲取類物件判斷此對映器是否已注入,沒有則標識當前解析資源,並呼叫addmapper注對映器,由於我們是在addmapper過來,對映器已經注入,所以不再呼叫,不然死迴圈了。那這個此時何時呼叫呢?我們接著往下看。

在這裡插入圖片描述

如果我們採用的標籤配置對映檔案。 在這裡插入圖片描述 如果通過resource或者xml屬性標識資源,此時建立解析類,但是注意這個構造方法沒有設定當前解析的檔案namespace.原因是namespace在不使用mapper介面的形式程式設計時,可以隨便填寫。 又回到xml解析,不同的是此時進行了對映器的註冊,當使用mapper介面程式設計,boundType不為空,然後進行註冊,在此呼叫了addMapper,同時表示對映檔案已解析,剛才咱們已經討論過。 在這裡插入圖片描述 如果通過class表示mapper介面,直接呼叫了addMapper,觸發檔案解析,不再贅述同時該方法也會解析mapper介面的註解,如果存在。

所以當使用註解時,對映檔案可以不用配置。但是建議配置空的xml檔案,namespace為mapper介面全類名,自動觸發對映器(mapper介面)的注入與註解的解析。如果你就是死活不配置,也闊以,請自行呼叫session.getConfiguration.addMapper(T.class).

總之,如果想使用mapper代理的方式,namespace與mapper介面全類名必須相同,至於需不需要同包同名,看你通過什麼樣的形式去配置,他們必須相同的還有個最重要的原因:解析sql語句所用的id為namespace+id,生成代理時,找尋sql介面對應的sql語句為介面全名+方法名。mapper檔案解析做了什麼及mapper代理物件的生成請聽下回分解。