我们现在能登陆、退出登陆、修改密码,但是这些跟完整的用户管理模块还差着很多。所以本小节我们来做用户模块CRUD操作中的查询功能,我说的查询指的是有条件分页查询。
在user.vue
页面中有查询用户记录的条件区域,我们可以设置具体的查询条件,如果什么条件都不设置的话,就是无条件分页查找用户记录。
一、定义模型层
因为查询条件是动态组合的,所以我们在持久层里面编写SQL语句的时候,要判断某个数据不为空,就把它添加到WHERE子句里面充当查询条件。因为是分页查询,所以我们要在TbUserDao.xml
文件中编写两条SQL语句,一个是用来查询总记录数,另一个用来查询分页记录。
因为SQL语句超级复杂,这里我先带着同学们从浅入深逐步拆解这个SQL语句。用户表中role字段是JSON数组格式,用户可以拥有多个角色。
如果我想查询根据角色名称查询用户,那么就要把用户表和角色表做表连接查询。
SELECT u.username
FROM tb_user u
JOIN tb_role r ON JSON_CONTAINS ( u.role, CONVERT ( r.id, CHAR ) )
WHERE r.role_name="超级管理员"
如果我现在想要查询用户的部门名称,但是有的员工没有部门,这就需要用左连接来联合部门表,这样可以保证所有的员工都会被查询出来,于是SQL语句进化成了下面的样子。
SELECT u.username,
d.dept_name AS deptName
FROM tb_user u
JOIN tb_role r ON JSON_CONTAINS ( u.role, CONVERT ( r.id, CHAR ) )
LEFT JOIN tb_dept d ON u.dept_id = d.id
WHERE r.role_name="超级管理员"
如果我想要把用户拥有的角色也显示出来,这下就麻烦了。因为一个用户可能拥有多个角色,这怎么能合并成一条用户信息呢。这里我要用`GROUP_CONCAT()`函数把多个角色名称拼接成一个字符串,举例如下:
SELECT GROUP_CONCAT( role_name separator "," ) FROM tb_role;
用上了GROUP_CONCAT()
函数,我们的SQL语句变成了下面的样子
SELECT u.username,
d.dept_name AS deptName,
(
SELECT GROUP_CONCAT( role_name separator "," )
FROM tb_role
WHERE JSON_CONTAINS ( u.role, CONVERT ( id, CHAR ) )
) AS roles
FROM tb_user u
JOIN tb_role r ON JSON_CONTAINS ( u.role, CONVERT ( r.id, CHAR ) )
LEFT JOIN tb_dept d ON u.dept_id = d.id
WHERE r.role_name="超级管理员"
了解过SQL语句的各种语法之后,下面才是我们正式要写的SQL语句。
<select id="searchUserByPage" parameterType="HashMap" resultType="HashMap">
SELECT
DISTINCT u.id,
u.name,
u.sex,
u.tel,
u.email,
d.dept_name AS dept,
u.hiredate,
u.root,
u.status,
( SELECT GROUP_CONCAT( role_name separator "," ) FROM tb_role WHERE JSON_CONTAINS ( u.role, CONVERT ( id, CHAR ) ) ) AS roles
FROM tb_user u
JOIN tb_role r ON JSON_CONTAINS ( u.role, CONVERT ( r.id, CHAR ) )
LEFT JOIN tb_dept d ON u.dept_id = d.id
WHERE 1=1
<if test="name!=null">
AND u.name LIKE "%${name}%"
</if>
<if test="sex!=null">
AND u.sex=#{sex}
</if>
<if test="role!=null">
AND r.role_name=#{role}
</if>
<if test="deptId!=null">
AND d.id=#{deptId}
</if>
<if test="status!=null">
AND u.status=#{status}
</if>
LIMIT #{start}, #{length}
</select>
<select id="searchUserCount" parameterType="HashMap" resultType="long">
SELECT
COUNT(DISTINCT u.id)
FROM tb_user u
JOIN tb_role r ON JSON_CONTAINS ( u.role, CONVERT ( r.id, CHAR ) )
WHERE 1=1
<if test="name!=null">
AND u.name LIKE "%${name}%"
</if>
<if test="sex!=null">
AND u.sex=#{sex}
</if>
<if test="role!=null">
AND r.role_name=#{role}
</if>
<if test="deptId!=null">
AND u.dept_id=#{deptId}
</if>
<if test="status!=null">
AND u.status=#{status}
</if>
</select>
在TbUserDao.java
接口中声明两个抽象方法。
public interface TbUserDao {
……
public ArrayList<HashMap> searchUserByPage(HashMap param);
public long searchUserCount(HashMap param);
}
二、定义业务层
在UserService.java
接口中声明抽象方法。
public interface UserService {
……
public PageUtils searchUserByPage(HashMap param);
}
在UserServiceImpl.java
类中实现抽象方法。
public class UserServiceImpl implements UserService {
……
@Override
public PageUtils searchUserByPage(HashMap param) {
ArrayList<HashMap> list = userDao.searchUserByPage(param);
long count = userDao.searchUserCount(param);
int start = (Integer) param.get("start");
int length = (Integer) param.get("length");
PageUtils pageUtils = new PageUtils(list, count, start, length);
return pageUtils;
}
}
三、定义Web层
创建SearchUserByPageForm.java
类,保存Ajax提交的数据。
@Data
@Schema(description = "查询用户分页记录表单")
public class SearchUserByPageForm {
@NotNull(message = "page不能为空")
@Min(value = 1, message = "page不能小于1")
@Schema(description = "页数")
private Integer page;
@NotNull(message = "length不能为空")
@Range(min = 10, max = 50, message = "length必须在10~50之间")
@Schema(description = "每页记录数")
private Integer length;
@Pattern(regexp = "^[\\u4e00-\\u9fa5]{1,10}$", message = "name内容不正确")
@Schema(description = "姓名")
private String name;
@Pattern(regexp = "^男$|^女$", message = "sex内容不正确")
@Schema(description = "性别")
private String sex;
@Pattern(regexp = "^[a-zA-Z0-9\\u4e00-\\u9fa5]{2,10}$", message = "role内容不正确")
@Schema(description = "角色")
private String role;
@Min(value = 1, message = "dept不能小于1")
private Integer deptId;
@Min(value = 1, message = "status不能小于1")
private Integer status;
}
在UserController.java
类中定义Web方法。
@RestController
@RequestMapping("/user")
@Tag(name = "UserController", description = "用户Web接口")
public class UserController {
……
@PostMapping("/searchUserByPage")
@Operation(summary = "查询用户分页记录")
@SaCheckPermission(value = {"ROOT", "USER:SELECT"}, mode = SaMode.OR)
public R searchUserByPage(@Valid @RequestBody SearchUserByPageForm form) {
int page = form.getPage();
int length = form.getLength();
int start = (page - 1) * length;
HashMap param = JSONUtil.parse(form).toBean(HashMap.class);
param.put("start", start);
PageUtils pageUtils = userService.searchUserByPage(param);
return R.ok().put("page", pageUtils);
}
}