[TOC]
在之前的代碼中我們的運作過程再梳理一下,首先我們執行Test,調用dao接口方法
接口的定義:
調用接口的實作類方法:
最後才是調用真正的sql:
上面的代碼是在接口實作類裡面自己去執行id,查找并執行mapper檔案裡面的sql,那麼我們想是不是可以減少一步呢?
如果我們不用自己實作接口,隻需要将接口的名字和mapper檔案的namespace對應起來,将接口裡面的方法名與sql語句标簽的id對應起來是不是就可以了呢?
事實上,mybatis提供了這樣的做法,這就是mapper動态代理。
首先主配置檔案(Mybatis.xml),在裡面配置資料庫連接配接資訊,注冊需要掃描的mapper檔案:
定義資料庫查詢的接口,裡面每一個接口的名字很重要,需要和mapper裡面每一條sql對應起來:
定義mapper檔案(namespace是接口的全限定類名):
那我們在使用的時候,需要使用sqlSession.getMapper()方法,裡面傳入的是接口,意思是通過接口的全限定名,也就是前面在mapper.xml檔案裡面配置的命名空間nameSpace,這樣一來,就是擷取到了代理類,将dao和mapper.xml檔案關聯起來了,而每條sql的id與我們的接口方法名字對應起來)
我們在前面還寫到過一個selectStudentMap()方法,但是裡面調用的是和SelectList()一樣的sql,在接口的實作類裡面我們自己處理了一下,但是現在使用自動實作的話,底層隻會調用SelectOne()或者SelectList()方法,是以這個方法會報錯,如果接受類型是list,那麼架構會自動使用selectList()方法,否則就會選擇selectOne()這個方法。
在這裡我們使用的是傳回的是map,是以自動選擇傳回selectOne()方法,那麼就會報錯。如果我們需要使用自動傳回map的話,可以自己定一個map,或者傳回list之後再處理,這個知識點後面再介紹,有興趣可以通路:mybatis的mapper傳回map結果集
打一個斷點在sqlSession.getMapper()方法上:
我們可以看到執行下面的接口方法(接口SqlSession的方法)
這是一個接口,我們可以看到實作接口的有兩個類,一個是DefaultSqlSession,一個是SqlSessionManager,我們需要看的是DefaultSqlSession下面的接口:
我們知道,在建立sqlsession的時候,confiiguration這個配置對象已經建立完成。跟進去,這是使用mapper注冊器對象的getMapper()方法,将目前的sqlSession對象傳遞進去:
我們跟進去源碼,可以發現裡面使用knownMappers.get(type)來擷取mapper代理工廠,這個konwnMappers是一個hashMap,這個hashMap裡面已經初始化了mapperProxyFactory對象了,擷取到工廠對象之後,再去使用sqlSession執行個體化:
執行個體化的時候,使用了mapper動态代理:
從下面的debug結果中我們可以看到,這是動态代理的結果,我們看到的是dao,但是動态代理對這個dao做了增強,實則是一個mapperProxy。
【作者簡介】:
秦懷,公衆号【秦懷雜貨店】作者,技術之路不在一時,山高水長,縱使緩慢,馳而不息。這個世界希望一切都很快,更快,但是我希望自己能走好每一步,寫好每一篇文章,期待和你們一起交流。
此文章僅代表自己(本菜鳥)學習積累記錄,或者學習筆記,如有侵權,請聯系作者核實删除。人無完人,文章也一樣,文筆稚嫩,在下不才,勿噴,如果有錯誤之處,還望指出,感激不盡~