用戶,角色,資源,聯(lián)合查詢(使用xml)

向xml低頭,沒(méi)錯(cuò),我向xml低頭了。
前文:
用戶,角色,資源,聯(lián)合查詢(使用注解SQL)

注解sql的那種provider的文件格式,可能真的不是mybatis主推的模式,場(chǎng)景欠缺的很多,而當(dāng)你硬把改場(chǎng)景用這種方式實(shí)現(xiàn)時(shí),反倒不優(yōu)雅了。還是回歸傳統(tǒng)吧,或許這就是xml這么多年屹立不倒的秘訣。

開始開始。

一段時(shí)間不見,gemini的表結(jié)構(gòu)被我改了改,結(jié)合各種方面優(yōu)化考慮,現(xiàn)在的他們是這樣的。
用戶表:

CREATE TABLE `g_user` (
  `id` int(32) NOT NULL AUTO_INCREMENT COMMENT '主鍵id',
  `user_id` bigint(32) NOT NULL COMMENT '用戶編號(hào)(業(yè)務(wù)id)',
  `identity_code` varchar(64) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL COMMENT '賬號(hào)',
  `nick_name` varchar(64) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '昵稱',
  `phone` varchar(32) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '聯(lián)系方式',
  `email` varchar(64) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '郵箱',
  `password` varchar(32) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '密碼',
  `lock` tinyint(1) DEFAULT '0' COMMENT '是否鎖定',
  `create_user_id` bigint(32) DEFAULT NULL COMMENT '創(chuàng)建人id',
  `update_user_id` bigint(32) DEFAULT NULL COMMENT '更新人id',
  `create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '創(chuàng)建時(shí)間',
  `update_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新時(shí)間',
  `rev` tinyint(8) DEFAULT '1' COMMENT '版本號(hào)',
  `delete_flag` tinyint(1) DEFAULT '0' COMMENT '刪除標(biāo)記',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

角色表:

CREATE TABLE `g_role` (
  `id` int(32) NOT NULL AUTO_INCREMENT COMMENT '主鍵id',
  `role_id` bigint(32) NOT NULL COMMENT '角色id',
  `role_code` varchar(64) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '角色編碼',
  `role_name` varchar(64) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '角色名稱',
  `create_user_id` bigint(32) DEFAULT NULL COMMENT '創(chuàng)建人id',
  `update_user_id` bigint(32) DEFAULT NULL COMMENT '更新人id',
  `create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '創(chuàng)建時(shí)間',
  `update_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新時(shí)間',
  `rev` tinyint(8) DEFAULT '1' COMMENT '版本號(hào)',
  `delete_flag` tinyint(1) DEFAULT '0' COMMENT '刪除標(biāo)記',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

用戶角色表:

CREATE TABLE `g_user_role` (
  `id` int(32) NOT NULL AUTO_INCREMENT COMMENT '主鍵id',
  `role_id` bigint(32) NOT NULL COMMENT '角色編碼',
  `user_id` bigint(32) NOT NULL COMMENT '用戶編碼',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

資源表:

CREATE TABLE `g_resource` (
  `id` int(32) NOT NULL AUTO_INCREMENT COMMENT '主鍵id',
  `resource_id` bigint(32) NOT NULL COMMENT '資源id',
  `resource_code` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '資源編碼',
  `resource_name` varchar(64) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '資源名稱',
  `create_user_id` int(32) DEFAULT NULL COMMENT '創(chuàng)建人id',
  `update_user_id` int(32) DEFAULT NULL COMMENT '更新人id',
  `create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '創(chuàng)建時(shí)間',
  `update_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新時(shí)間',
  `rev` tinyint(8) DEFAULT '1' COMMENT '版本號(hào)',
  `delete_flag` tinyint(1) DEFAULT '0' COMMENT '刪除標(biāo)記',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

角色資源表:

CREATE TABLE `g_res_role` (
  `id` int(32) NOT NULL AUTO_INCREMENT COMMENT '主鍵id',
  `role_id` bigint(32) NOT NULL COMMENT '角色id',
  `resource_id` bigint(32) NOT NULL COMMENT '資源id',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

總體模式同過(guò)去沒(méi)有區(qū)別,只是加了一些字段,改了一些名字,變化了一些規(guī)則。
首先,過(guò)去我的表主鍵都是自增id,但我在映射關(guān)系中,也是使用的自增id,其實(shí)是不科學(xué)的。過(guò)去也不是沒(méi)想到給它一個(gè)主鍵自增id,一個(gè)業(yè)務(wù)id,一個(gè)編碼,一個(gè)名字。所有的業(yè)務(wù)表都這么設(shè)計(jì)的模式。只是覺(jué)得有必要嗎?但是實(shí)際的項(xiàng)目探索之后,其實(shí)還是很有必要的。粒度越細(xì),其實(shí)可變化性就越多,分工也越明確。只是略有復(fù)雜需要處理,具體還是看個(gè)人和項(xiàng)目吧。總之我改成了現(xiàn)在的這樣。

開始切入正題。

我們現(xiàn)在需求的返回格式同過(guò)去一般無(wú)二。
1、用戶信息中帶角色列表,角色列表中再帶資源列表。
2、用戶信息中直接帶角色列表與資源列表。

對(duì)于vo文件我也沒(méi)有怎么改動(dòng)。除了字段更名和添加字段以外,格式,模式,基本同過(guò)去一致。

主要看xml。
其實(shí)本質(zhì)是類似的。還是使用resultMap進(jìn)行調(diào)控。
只是在注解sql中,用的是many=@Many()這樣的格式,在這里使用的就是collection標(biāo)簽。需要注意的是,所有的關(guān)聯(lián)字段(column)都必須顯式地被寫出來(lái),也就是不能依賴通配符(*)的查詢結(jié)果。

直接貼圖吧。

資源持久化類
ResourceMapper.java:

public interface ResourceMapper {

    /**
     * 根據(jù)roleId獲取資源信息
     */

    List<ResourceVo> selectByRoleId(Long roleId);
}

ResourceMapper.xml
很簡(jiǎn)單,只是普通的根據(jù)角色資源映射表查詢資源信息。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.hekiraku.gemini.mapper.ResourceMapper">
    <resultMap id="resourceInfo" type="com.hekiraku.gemini.domain.vo.ResourceVo">
    </resultMap>
    <select id="selectByRoleId" resultMap="resourceInfo">
        select gr.*
        from g_resource gr
        left join g_res_role grr on gr.resource_id = grr.resource_id
        where grr.role_id = #{roleId}
    </select>
</mapper>

接下來(lái)看角色
角色持久化類
RoleMapper.java

public interface RoleMapper {
/**根據(jù)userId獲取所有角色信息*/
    List<RoleVo> selectByUserId(Long userId);
}

RoleMapper.xml
<注意:這里的關(guān)聯(lián)字段是role_id,因此在下面的sql中就顯式地把它查了出來(lái)。>

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.hekiraku.gemini.mapper.RoleMapper">
    <resultMap id="roleInfo" type="com.hekiraku.gemini.domain.vo.RoleVo">
        <collection property="resources" column="role_id" javaType="java.util.List" select="com.hekiraku.gemini.mapper.ResourceMapper.selectByRoleId"/>
    </resultMap>
    <!--根據(jù)userId獲取相關(guān)角色信息-->
    <select id="selectByUserId" resultMap="roleInfo">
        select gr.*,grr.role_id as roleId
        from g_role gr
        left join g_user_role grr on gr.role_id = grr.role_id
        where grr.user_id = #{userId}
    </select>
</mapper>

用戶映射類
userMapper.java:

public interface UserMapper {
/**根據(jù)身份編碼獲取所有信息*/
    UserInfoVo selectByIdentityCode(String identityCode);
}

userMapper.xml:
<注意:這里的關(guān)聯(lián)字段是user_id,因此在下面的sql中就顯式地把它查了出來(lái)。>

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.hekiraku.gemini.mapper.UserMapper">

    <resultMap id="userInfo" type="com.hekiraku.gemini.domain.vo.UserInfoVo">
        <collection property="roles" column="user_id" ofType="com.hekiraku.gemini.domain.vo.RoleVo" javaType="java.util.List" select="com.hekiraku.gemini.mapper.RoleMapper.selectByUserId"/>
    </resultMap>
    <select id="selectByIdentityCode" resultMap="userInfo">
        select gu.user_id as userId,gu.*
        from g_user gu
        where gu.identity_code = #{identityCode}
    </select>
</mapper>

關(guān)聯(lián)字段是什么呢?就是兩個(gè)sql關(guān)聯(lián)在一起的那個(gè)共同的字段。所以在寫關(guān)聯(lián)查詢的時(shí)候,一定一定要注意的事,關(guān)聯(lián)字段一定要作為B的條件。

結(jié)果集

end

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容