前言
最近干了一個工作是使用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>
- column字段是指定我們要根據(jù)哪一個數(shù)據(jù)庫查詢字段進行判斷腮鞍,這個值可以是真實在數(shù)據(jù)庫中存在的屬性,也可以不存在莹菱,如果不存在的話移国,我們可以給實體類添加一個這個標識位屬性,或者使用繼承道伟,繼承父類迹缀,然后多加一個標志位屬性,放在子類上蜜徽。細心的讀者裹芝,肯定看出來,改造前的resultMap的type為RoleModel娜汁,改造后的type為ElasticRoleModel嫂易。
- javaType指定的是column那個字段在實體類中是什么類型的。
- value屬性就是我們剛剛指定的那個屬性值不同的情況掐禁,具體返回哪一個resultMap怜械。也就是說如果role_profile_flag屬性值為1的情況下,會返回ElasticRoleUserMap 的resultMap
- 如果你指定的那個值與所有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>
- 我們之所以繼承了使用鑒別器的那個resultMap是因為我們希望每個case返回的resultMap會包含所有鑒別器之外公共的變量
- resultMap中的collection就是嵌套的那些實體類的具體賦值實現(xiàn)障本,這里不做過多解釋
- 上面知識給出了三個例子,不光只有這三種,還可以倆倆的組合驾霜,或者是三個的組合形式
最后給出來案训,我們這個彈性查詢的基礎(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>
- 這里的roleFlag就是實體類中標志位寞酿,因為我們的這個標志位不是真實在數(shù)據(jù)庫中存在的家夺,所有傳入后,直接通過這種形式進行返回伐弹。as后的名稱一定要與鑒別器中的column字段一致秦踪。
- resultMap就是剛剛我們定義好的含有鑒別器的那個基礎(chǔ)的resultMap
后記
今天就先總結(jié)到這里,我也是當(dāng)時做的時候遇到了不少的坑掸茅,如果有什么其他的問題,可以在下方評論給我柠逞,咱們可以互相成長昧狮。謝謝大家。