用户,角色,资源,联合查询(使用注解SQL)

这个地方就是血泪,我一定要记录一下。

首先我们的表,有五张表。

用户表,角色表,资源表,用户-角色表,角色-资源表。
看一下表结构
用户表:


g_user.png

角色表:


g_role.png

用户-角色表:
g_user_role.png

资源表:
image.png

角色-资源表:


image.png

我们信息的层级关系是这样的。用户分配角色,角色分配资源
现在我们想要获取用户zhangSan的所有信息,我们需要联合查询的sql语句是:


联合查表.png

然后获得zhangSan的信息+角色信息+资源信息。

然后主要来看一下我们的代码结构
用户信息返回Vo:UserInfoVo

@Getter
@Setter
@NoArgsConstructor
@EqualsAndHashCode
@ToString
public class UserInfoVo implements Serializable {
    private String userName;
    private String userNum;
    @JsonIgnore
    private String password;
    private String phone;
    private String email;
    private String nickName;
    private String lock;
    private List<RoleVo> roles;
}

角色信息返回Vo:

@Getter
@Setter
@NoArgsConstructor
@EqualsAndHashCode
@ToString
public class RoleVo implements Serializable {
    private String roleName;
    private List<ResourceVo> resources;
}

资源返回Vo:

@Getter
@Setter
@NoArgsConstructor
@EqualsAndHashCode
@ToString
public class ResourceVo implements Serializable {
    private String resourceName;
}

接着就是最重要的,mapper文件的调用。
首先是根据角色id获取资源信息

public interface ResourceMapper {
    /**
     * 根据角色id获取资源信息
     * @param roleId
     * @return
     */
    @SelectProvider(type = ResourceDynaSqlProvider.class,method = "selectByRoleId")
    ResourceVo selectByRoleId(String roleId);
}

对应的sql文件

public class ResourceDynaSqlProvider {
    /**
     * 通过角色id查找资源表信息
     * @param roleId
     * @return
     */
    public String selectByRoleId(String roleId){
        SQL selectByRoleId = new SQL()
                .SELECT("gre.*")
                .FROM("g_resource gre,g_res_role grr")
                .WHERE("grr.role_id=#{roleId}")
                .AND()
                .WHERE("grr.res_id =gre.id");
        return selectByRoleId.toString();
    }
}

然后根据角色id获取角色信息

public interface RoleMapper {

    /**
     * 根据id获取角色与资源
     * @param id
     * @return
     */
    @SelectProvider(type = RoleDynaSqlProvider.class,method = "selectById")
    @Results(id = "roleMap", value = {
            @Result(property = "resources",column = "id",javaType = List.class,many = @Many(select = "com.hekiraku.gemini.mapper.ResourceMapper.selectByRoleId"))
    })
    RoleVo selectById(String id);
}

对应的sql

public class RoleDynaSqlProvider {
    /**
     * 根据id查找角色表信息
     * @param id
     * @return
     */
    public String selectById(String id){
        SQL selectById = new SQL()
                .SELECT("*")
                .FROM("g_role")
                .WHERE("id=#{id}");
        return selectById.toString();
    }
}

根据用户id或用户名获取用户信息

public interface UserMapper {

//    @SelectProvider(type=UserDynaSqlProvider.class,method = "selectAllByUserName")
//    UserInfoVo selectAllByUserName(String userName);

    @SelectProvider(type=UserDynaSqlProvider.class,method = "selectById")
    @Results(id = "userMap",value = {
            @Result(property = "roles",column = "id",javaType = List.class,many = @Many(select = "com.hekiraku.gemini.mapper.RoleMapper.selectById"))
    })
    UserInfoVo selectById(String id);
    @SelectProvider(type=UserDynaSqlProvider.class,method = "selectByUserName")
    @ResultMap("userMap")
    UserInfoVo selectByUserName(String userName);
}

对应的sql

public class UserDynaSqlProvider {
    /**
     * 通过id查询user表信息
     */
    public String selectById(String id){
        SQL selectById = new SQL()
                .SELECT("*")
                .FROM("g_user")
                .WHERE("id=#{id}");
        return selectById.toString();
    }
    /**
     * 通过username查询user表
     * @param userName
     * @return
     */
    public String selectByUserName(String userName){
        SQL selectIdByUserName = new SQL()
                .SELECT("id")
                .FROM("g_user")
                .WHERE("user_name=#{userName}");
        SQL selectAllById = new SQL()
                .SELECT("*")
                .FROM("g_user")
                .WHERE("id=("+selectIdByUserName.getSelf()+")");
        return selectAllById.toString();
    }
 
}

就这样,不需要写多重联合查询的sql,就可以办到多表数据组合了
调用一下。
好了,这就是我们需求的模样。


调用结果,层级结构.png

但是或许会觉得这样子的结构不好使用,那样我们只需要修改一发vo的返回。
吧UserInfoVo改成如下:

@Getter
@Setter
@NoArgsConstructor
@EqualsAndHashCode
@ToString
@ApiModel(value = "UserInfoVo",description = "用户返回信息")
public class UserInfoVo implements Serializable {
    @ApiModelProperty(notes = "用户名",example = "zhangSan")
    private String userName;
    @ApiModelProperty(notes = "用户编号",example = "201904031010001")
    private String userNum;
    @JsonIgnore
    @ApiModelProperty(notes = "密码",example = "123",hidden = true)
    private String password;
    @ApiModelProperty(notes = "手机号",example = "1322232313")
    private String phone;
    @ApiModelProperty(notes = "邮箱地址", example = "gemini@163.com")
    private String email;
    @ApiModelProperty(notes = "昵称",example = "碧落君(不)")
    private String nickName;
    @ApiModelProperty(notes = "是否冻结(0正常;1冻结)",example = "0")
    private String lock;
    @JsonIgnore
    private List<RoleVo> roles;
    @ApiModelProperty(name = "setRoles",notes = "角色信息",dataType = "Set<String>")
    public Set<String> getSetRoles(){
        Set<String> setRoles = new HashSet<>();
        if(roles.isEmpty()||roles==null){
            return setRoles;
        }
        Iterator<RoleVo> listRoles = roles.iterator();
        while(listRoles.hasNext()){
            RoleVo roleVo = listRoles.next();
            setRoles.add(roleVo.getRoleName());
        }
        return setRoles;
    }
    @ApiModelProperty(name = "SetResources",notes = "资源信息",dataType = "Set<String>")
    public Set<String> getSetResources(){
        Set<String> setResources = new HashSet<>();
        if(roles.isEmpty()||roles==null){
            return setResources;
        }
        Iterator<RoleVo> listRoles = roles.iterator();
        while(listRoles.hasNext()){
            RoleVo roleVo = listRoles.next();
            setResources.addAll(roleVo.getSetResources());
        }
        return setResources;
    }
}

同时要记得去掉RoleVo 中的返回list

@Getter
@Setter
@NoArgsConstructor
@EqualsAndHashCode
@ToString
public class RoleVo implements Serializable {
    private String roleName;
    @JsonIgnore
    private List<ResourceVo> resources;
}

然后调用之后,返回变成


平级结构.png

这种结构更加方便直接获取信息。

以上。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,204评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,091评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,548评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,657评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,689评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,554评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,302评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,216评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,661评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,851评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,977评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,697评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,306评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,898评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,019评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,138评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,927评论 2 355