Hap 通用mapper初探

介紹

Hap框架的通用Mapper實(shí)現(xiàn)了對單表的增刪改查,是在開源通用mapper(github地址)的基礎(chǔ)上涂屁,添加了對多語言支持等功能,以適應(yīng)Hap開發(fā)的需要心俗。眾所周知嘱函,MyBatis除了通過XML配置,還可以通過java注解來配置列另,通用mapper正是利用了MyBatis的SelectProvider芽腾、DeleteProvider等注解實(shí)現(xiàn)。

使用方法

自定義的mapper通過繼承通用mapper页衙,這樣mapper就實(shí)現(xiàn)了通用mapper接口所用方法的復(fù)用摊滔,其中必須指定通用Mapper的泛型,這樣就可以在service的實(shí)現(xiàn)類通過自定義mapper調(diào)用通用mapper接口中的所有方法店乐,自定義mapper如下所示:

public interface CustomMapper extends Mapper<DTO> {
    ...
}

原理剖析

通用mapper接口通過多層的接口繼承實(shí)現(xiàn)了方法的復(fù)用艰躺,其繼承鏈如下圖所示:


Mapper.png

最頂層的Mapper接口均包含一個與接口對應(yīng)的方法,下面具體結(jié)合SelectByPrimaryMapper的selectByPrimaryKey方法分析通用mapper的實(shí)現(xiàn)原理眨八,SelectProvider注解實(shí)現(xiàn)機(jī)制暫不予剖析描滔,僅從通用mapper使用該注解的層次予以分析。

public interface SelectByPrimaryKeyMapper<T> {
    @SelectProvider(type = BaseSelectProvider.class, method = "dynamicSQL")
    T selectByPrimaryKey(Object key);
}

在selectByPrimaryKey方法上運(yùn)用了SelectProvider注解,Mybatis官方文檔對其解釋如下:

這些可選的 SQL 注解(指SelectProvider, DeleteProvider, UpdateProvider, InsertProvider)允許你指定一個 類名和一個方法在執(zhí)行時來返回運(yùn)行允許創(chuàng)建動態(tài) 的 SQL踪古『ぃ基于執(zhí)行的映射語句, MyBatis 會實(shí)例化這個類,然后執(zhí)行由 provider 指定的方法.type 屬性是類。method 屬性是方法名伏穆。 引用自 Mybatis文檔

在示例中拘泞,selectByPrimaryKey方法可以理解為由BaseSelectProvider類中的method屬性對應(yīng)的方法實(shí)現(xiàn)(在本例中methond屬性指定的“dynamicSQL”,實(shí)際對應(yīng)BaseSelectMapper的抽象父類MapperTemplate的dynamicSQL方法,返回“dynamicSQL”字符串)枕扫,查看BaseSelectProvider源碼可見陪腌,
所有方法均返回拼接好的SQL字符串。
以下代碼截取自BaseSelectProvider.java:

// BaseSelectProvider.java
....
public String selectByPrimaryKey(MappedStatement ms) {
        final Class<?> entityClass = getEntityClass(ms);

        boolean isMl = EntityHelper.getEntityTable(entityClass).isSupportMultiLanguage();

        setResultType(ms, entityClass);
        StringBuilder sql = new StringBuilder();
        if (isMl) {
            sql.append(SqlHelper.selectAllColumns_TL(entityClass));
            sql.append(SqlHelper.fromTable_TL(entityClass, tableName(entityClass)));
            sql.append(SqlHelper.wherePKColumns_TL(entityClass));
        } else {
            sql.append(SqlHelper.selectAllColumns(entityClass));
            sql.append(SqlHelper.fromTable(entityClass, tableName(entityClass)));
            sql.append(SqlHelper.wherePKColumns(entityClass));
        }
        return sql.toString();
    }
...

這個方法接收一個MappedStatement對象(對應(yīng)xml映射文件的一個<select/>或<insert/>等節(jié)點(diǎn))烟瞧。
getEntityClass方法返回了節(jié)點(diǎn)對應(yīng)的DTO(通過自定義mapper的泛型獲仁肌)的類類型。
然后借助EntityHelper的getEntityTable方法獲取DTO @Table的值,即DTO對應(yīng)的表的信息的類参滴,獲取該表是否支持多語言信息(多語言信息的設(shè)置通過檢查DTO是否有@MutibleLanguage注解實(shí)現(xiàn))强岸。
通過條件語句根據(jù)是否支持多語言返回拼接的不同字符串,為簡化分析砾赔,以不支持多語言的表分析蝌箍。
第一步,創(chuàng)建了一個名為sql的StringBuilder類用來拼接字符串用于返回暴心。
第二步妓盲,拼接字符串。拼接的sql字符串由三個部分組成专普,這三個部分均通過SqlHelper的方法返回悯衬,返回類型均為字符串。分別為:

  • 字段檀夹。SqlHelper.selectAllColumns(entityClass)
  • 表筋粗。SqlHelper.fromTable(entityClass, this.tableName(entityClass))
  • 限定條件。SqlHelper.whereAllIfColumns(entityClass, this.isNotEmpty())
// SqlHelper.java
...
public static String getAllColumns(Class<?> entityClass) {
        Set<EntityColumn> columnList = EntityHelper.getColumns(entityClass);
        StringBuilder sql = new StringBuilder();
        Iterator var3 = columnList.iterator();

        while(var3.hasNext()) {
            EntityColumn entityColumn = (EntityColumn)var3.next();
            sql.append(entityColumn.getColumn()).append(",");
        }

       // 返回字符串形式如下"column1,column2,column3 ..."
        return sql.substring(0, sql.length() - 1);
    }
public static String selectAllColumns(Class<?> entityClass) {
        StringBuilder sql = new StringBuilder();
        sql.append("SELECT ");
        sql.append(getAllColumns(entityClass));
        sql.append(" ");

       // 返回字符串形式如下 "select column1, solumn2, column3"
        return sql.toString();
    }
...

以獲取字段為例击胜,主要通過EntityHelper的getColumns方法獲取所有字段的集合亏狰,然后遍歷集合,返回所有的字段拼接的字符串表示偶摔,最后與"select"暇唾、""拼接到一起并返回。
第三步辰斋,返回拼接好的select語句策州。

總結(jié)

通用Mapper的實(shí)現(xiàn)主要通過MyBatis的Provider注解,本質(zhì)上是一個通過泛型和注解動態(tài)獲取表的信息宫仗,拼接sql字符串的過程够挂。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市藕夫,隨后出現(xiàn)的幾起案子孽糖,更是在濱河造成了極大的恐慌枯冈,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,427評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件办悟,死亡現(xiàn)場離奇詭異尘奏,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)病蛉,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,551評論 3 395
  • 文/潘曉璐 我一進(jìn)店門炫加,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人铺然,你說我怎么就攤上這事俗孝。” “怎么了魄健?”我有些...
    開封第一講書人閱讀 165,747評論 0 356
  • 文/不壞的土叔 我叫張陵赋铝,是天一觀的道長。 經(jīng)常有香客問我诀艰,道長柬甥,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,939評論 1 295
  • 正文 為了忘掉前任其垄,我火速辦了婚禮苛蒲,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘绿满。我一直安慰自己臂外,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,955評論 6 392
  • 文/花漫 我一把揭開白布喇颁。 她就那樣靜靜地躺著漏健,像睡著了一般。 火紅的嫁衣襯著肌膚如雪橘霎。 梳的紋絲不亂的頭發(fā)上蔫浆,一...
    開封第一講書人閱讀 51,737評論 1 305
  • 那天,我揣著相機(jī)與錄音姐叁,去河邊找鬼瓦盛。 笑死,一個胖子當(dāng)著我的面吹牛外潜,可吹牛的內(nèi)容都是我干的原环。 我是一名探鬼主播,決...
    沈念sama閱讀 40,448評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼处窥,長吁一口氣:“原來是場噩夢啊……” “哼聋呢!你這毒婦竟也來了填硕?” 一聲冷哼從身側(cè)響起凫乖,我...
    開封第一講書人閱讀 39,352評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎俄讹,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體弄匕,經(jīng)...
    沈念sama閱讀 45,834評論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡颅悉,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,992評論 3 338
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了迁匠。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,133評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡驹溃,死狀恐怖城丧,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情豌鹤,我是刑警寧澤亡哄,帶...
    沈念sama閱讀 35,815評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站布疙,受9級特大地震影響蚊惯,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜灵临,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,477評論 3 331
  • 文/蒙蒙 一截型、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧儒溉,春花似錦宦焦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,022評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至涛碑,卻和暖如春精堕,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背蒲障。 一陣腳步聲響...
    開封第一講書人閱讀 33,147評論 1 272
  • 我被黑心中介騙來泰國打工歹篓, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人晌涕。 一個月前我還...
    沈念sama閱讀 48,398評論 3 373
  • 正文 我出身青樓滋捶,卻偏偏與公主長得像,于是被迫代替她去往敵國和親余黎。 傳聞我的和親對象是個殘疾皇子重窟,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,077評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 1. 簡介 1.1 什么是 MyBatis ? MyBatis 是支持定制化 SQL惧财、存儲過程以及高級映射的優(yōu)秀的...
    笨鳥慢飛閱讀 5,523評論 0 4
  • 官方文檔 簡介 入門 XML配置 XML映射文件 動態(tài)SQL Java API SQL語句構(gòu)建器 日志 一巡扇、 JD...
    拾壹北閱讀 3,546評論 0 52
  • 1 引言# 本文主要講解JDBC怎么演變到Mybatis的漸變過程扭仁,重點(diǎn)講解了為什么要將JDBC封裝成Mybait...
    七寸知架構(gòu)閱讀 76,473評論 36 980
  • 少年時癡迷武俠,很想有天被奇遇砸中厅翔,七經(jīng)八脈秒通乖坠,由一個平淡無奇的姑娘,蛻化成宇宙超級美少女刀闷。 事隔多年熊泵,斗轉(zhuǎn)星移...
    夏xiao安閱讀 325評論 0 0
  • 陡峭的崖壁, 孑然承受著風(fēng)的狂浪甸昏, 青絲亂舞顽分, 在空中抓不住虛無。 她一襲黑色衣裙施蜜, 站在岌岌可危的崖邊卒蘸, 眸子里...
    噴子的面具閱讀 239評論 0 0