向xml低頭,沒錯,我向xml低頭了。
前文:
用戶,角色,資源,聯(lián)合查詢(使用注解SQL)
注解sql的那種provider的文件格式,可能真的不是mybatis主推的模式,場景欠缺的很多,而當(dāng)你硬把改場景用這種方式實現(xiàn)時,反倒不優(yōu)雅了。還是回歸傳統(tǒng)吧,或許這就是xml這么多年屹立不倒的秘訣。
開始開始。
一段時間不見,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 '用戶編號(業(yè)務(wù)id)',
`identity_code` varchar(64) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL COMMENT '賬號',
`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)建時間',
`update_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新時間',
`rev` tinyint(8) DEFAULT '1' COMMENT '版本號',
`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)建時間',
`update_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新時間',
`rev` tinyint(8) DEFAULT '1' COMMENT '版本號',
`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)建時間',
`update_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新時間',
`rev` tinyint(8) DEFAULT '1' COMMENT '版本號',
`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;
總體模式同過去沒有區(qū)別,只是加了一些字段,改了一些名字,變化了一些規(guī)則。
首先,過去我的表主鍵都是自增id,但我在映射關(guān)系中,也是使用的自增id,其實是不科學(xué)的。過去也不是沒想到給它一個主鍵自增id,一個業(yè)務(wù)id,一個編碼,一個名字。所有的業(yè)務(wù)表都這么設(shè)計的模式。只是覺得有必要嗎?但是實際的項目探索之后,其實還是很有必要的。粒度越細(xì),其實可變化性就越多,分工也越明確。只是略有復(fù)雜需要處理,具體還是看個人和項目吧??傊腋某闪爽F(xiàn)在的這樣。
開始切入正題。
我們現(xiàn)在需求的返回格式同過去一般無二。
1、用戶信息中帶角色列表,角色列表中再帶資源列表。
2、用戶信息中直接帶角色列表與資源列表。
對于vo文件我也沒有怎么改動。除了字段更名和添加字段以外,格式,模式,基本同過去一致。
主要看xml。
其實本質(zhì)是類似的。還是使用resultMap進行調(diào)控。
只是在注解sql中,用的是many=@Many()這樣的格式,在這里使用的就是collection標(biāo)簽。需要注意的是,所有的關(guān)聯(lián)字段(column)都必須顯式地被寫出來,也就是不能依賴通配符(*)的查詢結(jié)果。
直接貼圖吧。
資源持久化類
ResourceMapper.java:
public interface ResourceMapper {
/**
* 根據(jù)roleId獲取資源信息
*/
List<ResourceVo> selectByRoleId(Long roleId);
}
ResourceMapper.xml
很簡單,只是普通的根據(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>
接下來看角色
角色持久化類
RoleMapper.java
public interface RoleMapper {
/**根據(jù)userId獲取所有角色信息*/
List<RoleVo> selectByUserId(Long userId);
}
RoleMapper.xml
<注意:這里的關(guān)聯(lián)字段是role_id,因此在下面的sql中就顯式地把它查了出來。>
<?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中就顯式地把它查了出來。>
<?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)字段是什么呢?就是兩個sql關(guān)聯(lián)在一起的那個共同的字段。所以在寫關(guān)聯(lián)查詢的時候,一定一定要注意的事,關(guān)聯(lián)字段一定要作為B的條件。

end