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> 標簽寫所有公用的屬性,也就是說這些屬性溪王,不會因為指定值的不同而有或無-->
  <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ù)庫中存在的屬性,也可以不存在莹菱,如果不存在的話移国,我們可以給實體類添加一個這個標識位屬性,或者使用繼承道伟,繼承父類迹缀,然后多加一個標志位屬性,放在子類上蜜徽。細心的讀者裹芝,肯定看出來,改造前的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就是實體類中標志位寞酿,因為我們的這個標志位不是真實在數(shù)據(jù)庫中存在的家夺,所有傳入后,直接通過這種形式進行返回伐弹。as后的名稱一定要與鑒別器中的column字段一致秦踪。
  2. resultMap就是剛剛我們定義好的含有鑒別器的那個基礎(chǔ)的resultMap

后記

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

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末板壮,一起剝皮案震驚了整個濱河市逗鸣,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌绰精,老刑警劉巖撒璧,帶你破解...
    沈念sama閱讀 206,378評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異笨使,居然都是意外死亡卿樱,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評論 2 382
  • 文/潘曉璐 我一進店門硫椰,熙熙樓的掌柜王于貴愁眉苦臉地迎上來繁调,“玉大人,你說我怎么就攤上這事靶草√阋龋” “怎么了?”我有些...
    開封第一講書人閱讀 152,702評論 0 342
  • 文/不壞的土叔 我叫張陵奕翔,是天一觀的道長裕寨。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么宾袜? 我笑而不...
    開封第一講書人閱讀 55,259評論 1 279
  • 正文 為了忘掉前任捻艳,我火速辦了婚禮,結(jié)果婚禮上试和,老公的妹妹穿的比我還像新娘讯泣。我一直安慰自己,他們只是感情好阅悍,可當(dāng)我...
    茶點故事閱讀 64,263評論 5 371
  • 文/花漫 我一把揭開白布好渠。 她就那樣靜靜地躺著,像睡著了一般节视。 火紅的嫁衣襯著肌膚如雪拳锚。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,036評論 1 285
  • 那天寻行,我揣著相機與錄音霍掺,去河邊找鬼。 笑死拌蜘,一個胖子當(dāng)著我的面吹牛杆烁,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播简卧,決...
    沈念sama閱讀 38,349評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼兔魂,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了举娩?” 一聲冷哼從身側(cè)響起析校,我...
    開封第一講書人閱讀 36,979評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎铜涉,沒想到半個月后智玻,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,469評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡芙代,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,938評論 2 323
  • 正文 我和宋清朗相戀三年吊奢,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片纹烹。...
    茶點故事閱讀 38,059評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡事甜,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出滔韵,到底是詐尸還是另有隱情逻谦,我是刑警寧澤,帶...
    沈念sama閱讀 33,703評論 4 323
  • 正文 年R本政府宣布陪蜻,位于F島的核電站邦马,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜滋将,卻給世界環(huán)境...
    茶點故事閱讀 39,257評論 3 307
  • 文/蒙蒙 一邻悬、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧随闽,春花似錦父丰、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,262評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至魏滚,卻和暖如春镀首,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背鼠次。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工更哄, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人腥寇。 一個月前我還...
    沈念sama閱讀 45,501評論 2 354
  • 正文 我出身青樓成翩,卻偏偏與公主長得像,于是被迫代替她去往敵國和親赦役。 傳聞我的和親對象是個殘疾皇子麻敌,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,792評論 2 345

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