Boss项目:员工查询+员工新增(2.5)

一、员工查询:

在此之前员工domian、service、mapper已准备好。

image-20260222133809947

①新建EmployeeController:

@Controller
@RequestMapping("/employee")
public class EmployeeController {

    @Autowired
    private DepartmentService departmentService;
    @Autowired
    private 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;父类QueryObjectcurrentPage(当前页)、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

   @Override
    public List<Department> findAll() {
        List<Department> departmentList= departmentMapper.queryAll();
        return departmentList;
    }

由于之前写过List<Department> departmentList= departmentMapper.queryAll();直接拿来用;

⑤实现 employeeService.queryByPage(employeeQo)方法:

employeeService

employeeServiceImpl:

    @Override
    public 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() != -1
                    sql += "and dept_id=#{deptId}";


                }
            }
            return sql;
        }

    }
    

小结:

departmentService.findAll();为什么是查询所有部门?

image-20260222140750946

①将所有部门信息显示到下拉框中;

②当我们点击查询按钮时,会将keyworddeptId一起提交到后端 /employee/list 接口

③使用 @ModelAttribute("qo") EmployeeQo qo 接收参数。

前端传来的 keyworddeptId 会被自动封装到 qo 对象中(deptIdEmployeeQo 的字段,keyword 继承自父类 QueryObject)。

④查询出数据并返回给前端

二、员工新增:

①新建EmployeeController:

@Controller
@RequestMapping("/employee")
public class EmployeeController {

    @Autowired
    private DepartmentService departmentService;
    @Autowired
    private EmployeeService employeeService;
    @Autowired
    private RoleService roleService;

    @GetMapping("/input")
    @RequireLogin
    public String inputGet(Long id,Map<String,Object> map){

        if(!(StringUtils.isEmpty(id))){
            //编辑  employee
            Employee employee = employeeService.findById(id);
            map.put("employee",employee);
        }


        //新增+编辑 depts  roles
        List<Department> departmentList =departmentService.findAll();
        map.put("depts",departmentList);
        //roles
        List<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))){
            //编辑  employee
            Employee 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 {

    @Autowired
    private RoleMapper roleMapper;

    @Override
    public List<Role> findAll() {
        List<Role> roles = roleMapper.queryAll();
        return roles;
    }
}

新建RoleMapper:

public interface RoleMapper {

}

④实现roleService.findAll()方法:

RoleService

​ ↓

RoleServiceImpl:

@Service
public class RoleServiceImpl implements RoleService {

    @Autowired
    private RoleMapper roleMapper;

    @Override
    public 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
    @ResponseBody
    public 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;
	//分配员工角色id
    private List<Long> ids;

}

因为employeerole多对多关系,所以要有一张中间表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() != -1
                        sql += "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
    

image-20260222164012559

查询出员工和部门表的全部信息,将employee.dept_id=department.id进行匹配,但前端只显示出员工部分信息和部门名称,即<td>${(employee.dept.name)!}</td> <!-- 员工所属部门名称 -->

②private List roles:

  • 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 ids:

  • 新增和编辑都需要修改两张表,即employee表和employee_role表,前面①和②只作为查询,而③则是要更新表,是前端给后端临时传参字段

    input.ftl 页面新增时,在选择角色后,JS 会把右侧选择框的角色 ID 收集成数组,提交时传给后端;

    后端接收并赋值给 Employee 对象的 ids 字段;

未完待续。。。

posted on 2026-02-23 07:58  冬冬咚  阅读(15)  评论(0)    收藏  举报