这个地方就是血泪,我一定要记录一下。
首先我们的表,有五张表。
用户表,角色表,资源表,用户-角色表,角色-资源表。
看一下表结构
用户表:
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
这种结构更加方便直接获取信息。
以上。