Mybatis之discriminator(鑒別器)詳解

前言

最近干了一個工作是使用discriminator去寫一個新的API,那么寫這個新的API原因是什么呢?原因是這樣的:我們的項目使用Mybatis,我們項目中有一個實體類叫做User,在User中還含有很多別的實體類,例如Role,Permission,Address等(有經(jīng)驗的肯定知道這種嵌套實體類的情況,使用<association>和<collection>)。然后之前有一個API是把User以及關(guān)聯(lián)的所有實體類都給查出來。從現(xiàn)在看起來,并沒有什么不合理的地方。

但是隨著項目不斷擴大很多地方需要查詢User一個這有一個現(xiàn)成的API就直接使用了,哪怕需求只是獲取一個簡單的用戶名稱。這種大材小用的地方多了,不但導(dǎo)致了調(diào)用的地方回來的很慢,還導(dǎo)致了服務(wù)器性能的浪費。

很多人可定會說就是因為懶,如果多謝幾個sql,每個sql按照需要返回不就好了嗎?確實可以這樣去做,但是這導(dǎo)致了,我們得不停的寫重復(fù)的sql,然后寫resultMap,最后返回。這種重復(fù)的工作,對于一個程序員是不可以容忍的。

所以,引出了今天的主人公——discriminator。

正文

我們應(yīng)該如何使用鑒別器呢?別著急咱們慢慢看。

如果沒有使用鑒別器,返回實體類以及嵌套的實體類的resultMap應(yīng)該是這樣的:

<resultMap extends="BaseResultMap" id="EhmFullExcludeUserResultMap" type="com.test.RoleModel">
        <result column="transaction_id" jdbcType="VARCHAR" property="transactionId" />
            <collection column="role_id" ofType="com.test.model.UserModel" property="userList" select="com.test.mapper.selectUserByRoleId" />
        <collection column="role_id" ofType="com.test.model.GroupModel" property="groupList" select="com.test.mapper.selectGroupByRoleId" />
        <collection column="role_id" ofType="com.test.model.PermissionModel" property="permissionList" select="com.test.mapper.selectPermissionByRoleId" />
    </resultMap>

鑒別器使用后的基本寫法是這樣的:

<resultMap extends="BaseResultMap" id="ElasticRoleMap" type="com.test.ElasticRoleModel">
  <!--可以在這里使用<result> 標(biāo)簽寫所有公用的屬性,也就是說這些屬性,不會因為指定值的不同而有或無-->
  <discriminator javaType="java.lang.Integer" column="role_profile_flag">
              <case value="1" resultMap="com.test.mapper.ElasticRoleUserMap"/>
              <case value="2" resultMap="com.test.mapper.ElasticRoleGroupMap"/>
              <case value="4" resultMap="com.test.mapper.ElasticRolePermissionMap"/>
              <case value="6" resultMap="com.test.mapper.ElasticRoleGroupAndPermissionMap"/>
  </discriminator>
</resultMap>
  1. column字段是指定我們要根據(jù)哪一個數(shù)據(jù)庫查詢字段進行判斷,這個值可以是真實在數(shù)據(jù)庫中存在的屬性,也可以不存在,如果不存在的話,我們可以給實體類添加一個這個標(biāo)識位屬性,或者使用繼承,繼承父類,然后多加一個標(biāo)志位屬性,放在子類上。細心的讀者,肯定看出來,改造前的resultMap的type為RoleModel,改造后的type為ElasticRoleModel。
  2. javaType指定的是column那個字段在實體類中是什么類型的。
  3. value屬性就是我們剛剛指定的那個屬性值不同的情況,具體返回哪一個resultMap。也就是說如果role_profile_flag屬性值為1的情況下,會返回ElasticRoleUserMap 的resultMap
  4. 如果你指定的那個值與所有case中的值都不相同,則會把最外層的resultMap,也就是ElasticRoleMap進行返回,其中就會返回這個resultMap最基本的那些屬性(鑒別器之外的值)。

下面給出每個case返回的resultMap的樣例:

<!-- Only get the user detail model -->
    <resultMap extends="ElasticRoleMap" id="ElasticRoleUserMap" type="com.test.EhmElasticRoleModel">
        <collection column="role_id" ofType="com.kingland.platform.user_access.common.model.UserModel" property="userList" select="com.kingland.platform.user_access.mapper.RoleModelMapper.selectUserByRoleId" />
    </resultMap>

    <!-- Only get the user group model -->
    <resultMap extends="ElasticRoleMap" id="ElasticRoleGroupMap" type="com.test.EhmElasticRoleModel">
        <collection column="role_id" ofType="com.kingland.platform.user_access.common.model.GroupModel" property="groupList" select="com.kingland.platform.user_access.mapper.RoleModelMapper.selectGroupByRoleId" />
    </resultMap>

    <!-- Only get the user permission model -->
    <resultMap extends="ElasticRoleMap" id="ElasticRolePermissionMap" type="com.test.EhmElasticRoleModel">
        <collection column="role_id" ofType="com.kingland.platform.user_access.common.model.PermissionModel" property="permissionList" select="com.kingland.platform.user_access.mapper.RoleModelMapper.selectPermissionByRoleId" />
    </resultMap>
  1. 我們之所以繼承了使用鑒別器的那個resultMap是因為我們希望每個case返回的resultMap會包含所有鑒別器之外公共的變量
  2. resultMap中的collection就是嵌套的那些實體類的具體賦值實現(xiàn),這里不做過多解釋
  3. 上面知識給出了三個例子,不光只有這三種,還可以倆倆的組合,或者是三個的組合形式

最后給出來,我們這個彈性查詢的基礎(chǔ)sql,他只是負責(zé)了最基本的查詢,這個sql所查詢出來的數(shù)據(jù),無論在鑒別器case中,或者不在鑒別器case中,都會進行返回,因為他們不是嵌套的那些實體類。

    <select id="getElasticRoleByRoleIdAndRoleFlag" parameterType="map" resultMap="ElasticRoleMap">
        SELECT
            ro.*,
            out_tran.transaction_id as validated_transaction_id,
            #{roleFlag, jdbcType=INTEGER} as role_profile_flag
        FROM
            platform.role ro
            
        WHERE ro.role_id = #{roleId,jdbcType=BIGINT}
    </select>
</mapper>


  1. 這里的roleFlag就是實體類中標(biāo)志位,因為我們的這個標(biāo)志位不是真實在數(shù)據(jù)庫中存在的,所有傳入后,直接通過這種形式進行返回。as后的名稱一定要與鑒別器中的column字段一致。
  2. resultMap就是剛剛我們定義好的含有鑒別器的那個基礎(chǔ)的resultMap

后記

今天就先總結(jié)到這里,我也是當(dāng)時做的時候遇到了不少的坑,如果有什么其他的問題,可以在下方評論給我,咱們可以互相成長。謝謝大家。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,836評論 6 540
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,275評論 3 428
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,904評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,633評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 72,368評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,736評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,740評論 3 446
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,919評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,481評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 41,235評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,427評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,968評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,656評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,055評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,348評論 1 294
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,160評論 3 398
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 48,380評論 2 379

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