Boss项目:员工查询+员工新增(2.5)
一、员工查询:
在此之前员工domian、service、mapper已准备好。

①新建EmployeeController:
@Controller
@RequestMapping("/employee")
public class EmployeeController {@Autowiredprivate DepartmentService departmentService;@Autowiredprivate EmployeeService employeeService;@GetMapping(value = "/list")public String listGet(@ModelAttribute("qo") EmployeeQo employeeQo,Map<String, Object> map) {//1.depts 查询出来所有部门List<Department> departmentList =departmentService.findAll();map.put("depts",departmentList);//2.result PageInfo<Employee> 分页PageInfo<Employee> employeePageInfo = employeeService.queryByPage(employeeQo);map.put("result",employeePageInfo);return "employee/list";}@PostMapping(value = "/list")public String listPost(@ModelAttribute("qo") EmployeeQo employeeQo, Map<String, Object> map){//1.depts 查询出来所有部门List<Department> departmentList =departmentService.findAll();map.put("depts",departmentList);//2.result PageInfo<Employee> 分页PageInfo<Employee> employeePageInfo = employeeService.queryByPage(employeeQo);map.put("result",employeePageInfo);return "employee/list";}}
@ModelAttribute("qo")是把前端请求参数自动封装到指定的 Java 对象中,并给对象起别名qo。
②新建EmployeeQo:
@Data
@AllArgsConstructor
@NoArgsConstructor
public class EmployeeQo extends QueryObject {private Long deptId;}
根据前端所需参数来写EmployeeQo;父类QueryObject 有 currentPage(当前页)、pageSize(每页条数)、keyword(通用关键字)等字段,因此子类EmployeeQo只需写deptId字段即可。
③修改Employee类:
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Employee {private Long id;private String name;private String password;private String email;private Integer age;private Boolean admin;private Long deptId;//多对一private Department dept;}
由于显示出员工信息的同时要显示员工所属部门,员工与部门为多对一的关系,因此要在Employee类添加private Department dept;采用左外连接。
④实现departmentService.findAll()方法:
departmentService
↓
DepartmentServiceImpl
@Overridepublic List<Department> findAll() {List<Department> departmentList= departmentMapper.queryAll();return departmentList;}
由于之前写过List<Department> departmentList= departmentMapper.queryAll();直接拿来用;
⑤实现 employeeService.queryByPage(employeeQo)方法:
employeeService
↓
employeeServiceImpl:
@Overridepublic PageInfo<Employee> queryByPage(EmployeeQo employeeQo) {PageHelper.startPage(employeeQo.getCurrentPage(),employeeQo.getPageSize());List<Employee> employeeList = employeeMapper.queryByCondition(employeeQo);PageInfo<Employee> info = new PageInfo<>(employeeList);return info;}
↓
EmployeeMapper:
实现queryByCondition方法
@Results({@Result(property = "id", column = "id", id = true),@Result(property = "name", column = "name"),@Result(property = "password", column = "password"),@Result(property = "email", column = "email"),@Result(property = "age", column = "age"),@Result(property = "admin", column = "admin"),@Result(property = "deptId", column = "dept_id"),@Result(property = "dept.id", column = "did"),@Result(property = "dept.name", column = "dname"),@Result(property = "dept.sn", column = "sn")})@SelectProvider(type = SQLProvider.class, method = "queryByCondition")List<Employee> queryByCondition(EmployeeQo employeeQo);class SQLProvider {public String queryByCondition(EmployeeQo employeeQo) {String sql = "select employee.*,department.id did,department.name dname ,sn " +"from employee left outer join department on employee.dept_id=department.id " +"where 1=1 ";if (employeeQo != null) {if (!StringUtils.isEmpty(employeeQo.getKeyword()))sql += "and (employee.name like concat ('%',#{keyword},'%') or email like concat ('%',#{keyword},'%'))";if (employeeQo.getDeptId() != null && employeeQo.getDeptId() != -1) {//employeeQo.getDeptId() != -1sql += "and dept_id=#{deptId}";}}return sql;}}
小结:
departmentService.findAll();为什么是查询所有部门?

①将所有部门信息显示到下拉框中;
②当我们点击查询按钮时,会将keyword和deptId一起提交到后端 /employee/list 接口
③使用 @ModelAttribute("qo") EmployeeQo qo 接收参数。
前端传来的 keyword 和 deptId 会被自动封装到 qo 对象中(deptId 是 EmployeeQo 的字段,keyword 继承自父类 QueryObject)。
④查询出数据并返回给前端
二、员工新增:
①新建EmployeeController:
@Controller
@RequestMapping("/employee")
public class EmployeeController {@Autowiredprivate DepartmentService departmentService;@Autowiredprivate EmployeeService employeeService;@Autowiredprivate RoleService roleService;@GetMapping("/input")@RequireLoginpublic String inputGet(Long id,Map<String,Object> map){if(!(StringUtils.isEmpty(id))){//编辑 employeeEmployee employee = employeeService.findById(id);map.put("employee",employee);}//新增+编辑 depts rolesList<Department> departmentList =departmentService.findAll();map.put("depts",departmentList);//rolesList<Role> roleList =roleService.findAll();map.put("roles",roleList);return "employee/input";}}
①新增和编辑都使用/employee/input路由,只是带不带id的区别;
| 操作 | 跳转 URL | 后端 id 参数 | employee 对象 | 页面表现 |
|---|---|---|---|---|
| 新增 | /employee/input |
null | 不存在 | 显示密码框、用户名可编辑 |
| 编辑 | /employee/input?id=1 |
1(员工 ID) | 存在(查库) | 隐藏密码框、用户名只读、回显数据 |
②input.ftl 是新增 + 编辑共用页面,通过 ${employee??} 判断是否为编辑模式,通过 id 区分新增 / 编辑;统一使用/employee/saveOrUpdate表单提交;
逻辑部分:
首先需要查询所有部门信息:
List<Department> departmentList =departmentService.findAll();map.put("depts",departmentList);
其次要查询出全部角色:
List<Role> roleList =roleService.findAll();map.put("roles",roleList);
若为编辑,则要回显employee:
if(!(StringUtils.isEmpty(id))){//编辑 employeeEmployee employee = employeeService.findById(id);map.put("employee",employee);}
②修改Employee类:
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Employee {private Long id;private String name;private String password;private String email;private Integer age;private Boolean admin;private Long deptId;private Department dept;//多对多private List<Role> roles;}
③补全Role:
新建Role实体类:
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Role {private Long id;private String name;private String sn;}
新建RoleService:
public interface RoleService {List<Role> findAll();
}
新建RoleServiceImpl:
@Service
public class RoleServiceImpl implements RoleService {@Autowiredprivate RoleMapper roleMapper;@Overridepublic List<Role> findAll() {List<Role> roles = roleMapper.queryAll();return roles;}
}
新建RoleMapper:
public interface RoleMapper {}
④实现roleService.findAll()方法:
RoleService
↓
RoleServiceImpl:
@Service
public class RoleServiceImpl implements RoleService {@Autowiredprivate RoleMapper roleMapper;@Overridepublic List<Role> findAll() {List<Role> roles = roleMapper.queryAll();return roles;}
}
↓
RoleMapper:
public interface RoleMapper {@Select("select * from role")@Results({@Result(property = "id",column = "id",id = true),@Result(property = "name",column = "name"),@Result(property = "sn",column = "sn")})List<Role> queryAll();}
④新增/编辑表单提交部分:
EmployeeController类:
@PostMapping("/saveOrUpdate")@RequireLogin@ResponseBodypublic Result saveOrUpdate(@RequestBody Employee employee){try {if(StringUtils.isEmpty(employee.getId())){//新增employeeService.save(employee);}else {//编辑//employeeService.edit(employee);}} catch (Exception e) {e.printStackTrace();return Result.fail(e.getMessage());}return Result.success();}
⑤修改Employee类:
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Employee {private Long id;private String name;private String password;private String email;private Integer age;private Boolean admin;private Long deptId;private Department dept;private List<Role> roles;//分配员工角色idprivate List<Long> ids;}
因为employee和role是多对多关系,所以要有一张中间表employee_role维护,所以新增employee表的同时也要更新employee_role表
小结:
①private Department dept:
问题:仅靠 employee 表的 dept_id,只能拿到部门数字 ID(如 2),无法直接获取部门名称(如 “采购部”)。
-
员工与部门是多对一关系;
增加
Department dept;,表达 “员工归属某部门” 的多对一关系,符合面向对象设计思想;class SQLProvider {public String queryByCondition(EmployeeQo employeeQo) {String sql = "select employee.*,department.id did,department.name dname ,sn " +"from employee left outer join department on employee.dept_id=department.id " +"where 1=1 ";if (employeeQo != null) {if (!StringUtils.isEmpty(employeeQo.getKeyword()))sql += "and (employee.name like concat ('%',#{keyword},'%') or email like concat ('%',#{keyword},'%'))";if (employeeQo.getDeptId() != null && employeeQo.getDeptId() != -1) {//employeeQo.getDeptId() != -1sql += "and dept_id=#{deptId}";}}return sql;}}若只是分页的话(即employeeQo=null),将执行
select employee.*,department.id did,department.name dname ,sn from employee left outer join department on employee.dept_id=department.id

查询出员工和部门表的全部信息,将employee.dept_id=department.id进行匹配,但前端只显示出员工部分信息和部门名称,即<td>${(employee.dept.name)!}</td> <!-- 员工所属部门名称 -->
②private List
-
employee与role是多对多关系,需要中间表employee_role维护;
当点击编辑按钮的时候,会携带id,在EmployeeServiceImpl中判断是否为admin,若是admin则直接返回employee;若不是admin,则
employee.setRoles(roles);,返回employee;在EmployeeRoleMapper中写SQL语句,查询role表全部信息,采用内连接,条件为er.employee_id=#{id}
select r.* from employee_role er inner join role r on er.role_id=r.id where er.employee_id=#{id}<!-- 关键代码:遍历employee.roles,显示已分配的角色 --> <#list (employee.roles)! as r><option value="${r.id}">${r.name}</option> </#list>所以
List<Role> roles首要作用是回显数据,但底层是多对多关系的对象化封装
③private List
-
新增和编辑都需要修改两张表,即employee表和employee_role表,前面①和②只作为查询,而③则是要更新表,是前端给后端临时传参字段;
在
input.ftl页面新增时,在选择角色后,JS 会把右侧选择框的角色 ID 收集成数组,提交时传给后端;后端接收并赋值给
Employee对象的ids字段;
未完待续。。。
