Tlias智能学习辅助系统总结

序:模块开发顺序


首先,我们先来理清各个模块开发的顺序

例:班级管理(子模块1),学员管理(子模块2)∈ 班级学员管理(父模块)

学员管理(学员所属班级)∈ 班级管理


那么对Tlias项目分析 ,拥有三个父模块(忽略登录功能),分别为

1.系统信息管理(父模块): 部门管理,员工管理

又 员工管理(员工所属部门)∈ 部门管理

2. 班级学员管理(父模块):班级管理,学员管理

又 学员管理(学员所属班级)∈ 班级管理 

班级学员管理(班级,学员所属员工[教师])∈系统信息管理

3. 数据统计管理(父模块):员工信息统计,学员信息统计

员工信息统计 ∈ 系统信息管理      学员信息统计 ∈ 班级学员管理

故可以得到开发模块的流程:

模块功能[接口]开发的流程(课程所建议流程)为

正:各模块开发

仅列出各个模块开发过程中觉得重要的部分


1.部门管理

1.1 前端各请求参数的接收方式

补丁:可以直接用类来接收,不需要@RequestBody注解,自动绑定

public Result<String> save(@RequestBody CategoryDTO categoryDTO)

1.1.1参数请求:

传递参数:

例如:/depts?id=1

接受请求:

推荐:将方法形参与前端参数名保持一致,自动识别(省略@RequestParam)

@DeleteMapping("/depts")
public Result deleteById(Integer id)

其他方式:
1.直接将请求体对象HttpServletRequest作为方法形参
2.RequestParam注解进行绑定(requir.通过@ed = false)时为非必须绑定参数(默认为true)

public Result deleteById(@RequestParam(value = "id" required = true) Integer deptid)

当传递的参数为数组时

例:/emps?ids=1,2,3

可默认用数组接受参数,此时会自动绑定参数

public Result delete(int[] ids)

若要用列表List等接收参数,需要使用@RequestParam 标注,才能绑定参数

public Result delete(@RequestParam List<Integer> ids)

当传递的参数过于复杂时

例:/emps?name=张&gender=1&begin=2007-09-01&end=2022-09-01&page=1&pageSize=10

可以自定义一个类来接受参数:

@Data
public class EmpQueryParam {
    private Integer page = 1;
    private Integer pageSize = 10;
    private String name;
    private Integer gender;
    @DateTimeFormat(pattern = "yyyy-MM-dd")
    private LocalDate begin;
    @DateTimeFormat(pattern = "yyyy-MM-dd")
    private LocalDate end;
}
@GetMapping
public Result list(EmpQueryParam e) 
1.1.2  json请求

传递参数:

例如

{
  "image": "https://web-framework.oss-cn-hangzhou.aliyuncs.com/2022-09-03-07-37-38222.jpg",
  "username": "linpingzhi",
  "name": "林平之",
  "gender": 1,
  "job": 1,
  "entryDate": "2022-09-18",
  "deptId": 1,
  "phone": "18809091234",
  "salary": 8000,
  "exprList": [
      {
         "company": "百度科技股份有限公司",
         "job": "java开发",
         "begin": "2012-07-01",
         "end": "2019-03-03"
      },
      {
         "company": "阿里巴巴科技股份有限公司",
         "job": "架构师",
         "begin": "2019-03-15",
         "end": "2023-03-01"
      }
   ]
}

接受请求:

json格式的参数,往往通过一个实体对象接收

规则:json格式的参数名与方法形参对象的属性名保持一致,并使用@RequestBody注解标注

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Dept {
    private Integer id;
    private String name;
    LocalDateTime createTime;
    LocalDateTime updateTime;
}
@PostMapping("/depts")
public Result addDept(@RequestBody Dept dept)
1.1.3路径参数

传递参数:

需要用@PathVariable注解标注

public Result getInfo(@PathVariable("id") Integer deptid)

路径参数和方法形参一致时,可以简化

@GetMapping("/depts/{id}")
public Result getInfo(@PathVariable Integer id)

当传递多个路径参数时

如:/students/violation/{id}/{score}

方法需要标记多个形参

@PutMapping("/violation/{id}/{score}")
public Result violation(@PathVariable Integer id, @PathVariable Integer score)

2.员工管理

2.1分页查询PageHelper

PageHelper依赖引入[pom.xml]:

        <!--分页插件PageHelper-->
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper-spring-boot-starter</artifactId>
            <version>1.4.7</version>
        </dependency>

PageHelper使用注意事项:

PageHelper的注意事项

1.SQL语句不能加分号,不然无法修改

2.PageHelper仅进行一次拦截,只对后面第一次调用SQL语句生效

3.Page<>数据结构继承了ArrayList ,对ArrayList进行了改造封装

@Override
    public PageResult<Emp> list(EmpQueryParam e) {

      

        //设置分页参数
        //Page为页码
        //PageSize为每页展示的数据数
        PageHelper.startPage(e.getPage(),e.getPageSize());

        //调用Mapper
        //直接用Page封装结果(Page类由PageHelper提供,封装了total等分页查询参数)
        //empMapper.list(e)返回的参数为List<>类型
        Page<Emp> p = (Page<Emp>)empMapper.list(e);

        //返回结果
        //PageResult<>为自定义类
        return new PageResult<Emp>(p.getTotal(),p.getResult());

    }

PageResult类:

@Data
@AllArgsConstructor
@NoArgsConstructor
public class PageResult<T> {
    private long total;
    private List<T> rows;
}

使用泛型<T>的意义是 定义一个PageResult类可以用于多个模块 ,避免代码臃肿

2.2 事务管理

背景描述:

员工管理的新增员工功能涉及到两张表 emp(员工表) ,emp_expr(员工经历表)

新增员工的Service层分别调用了两个Mapper接口,empMapper 和 empExprMapper

当empMapper调用失败,但是empExprMapper调用成功时,就会出现两张表数据不同步的现象。

为了避免这种现象 ,就可以使用事务管理(Transactional)

当一个方法被事务管理标记后

当方法中出现异常时,方法中对数据库的操作都会被撤销(回滚)

    @Transactional(rollbackFor = RuntimeException.class,propagation = REQUIRED)
    //@Transactional 注解用于声明一个事务方法,它可以应用于方法级别或类级别。
    //回滚适用情况默认为RuntimeException
    //propagation默认为REQUIRED(加入父事务[存在时]) 当需要强制为新事务时为 REQUIRED_NEW
    @Override
    public void add(Emp emp) {

        empMapper.add(emp);
        //调用完emp的add方法后,emp的id获得返回值
        List<EmpExpr> exprList = emp.getExprList();

        if(!CollectionUtils.isEmpty(exprList)){
            //System.out.println(emp.getId());
            empExprMapper.addBatch(emp.getId(),exprList);
        }
    }

2.3 SQL应用

2.3.1添加信息

问题描述:emp的Mapper层在执行Insert语句时,需要获取信息插入后的id,交给empExpr的Mapper执行

使用useGeneratedKeyskeyProperty属性 来取得id

    <insert id="add" useGeneratedKeys="true" keyProperty="id">
        insert into emp(username, name, gender, image, dept_id, entry_date, job,salary,phone,create_time,update_time)
        values(#{username},#{name},#{gender},
        <choose>
            <when test="image == ''">
                'https://web-framework.oss-cn-hangzhou.aliyuncs.com/2023/1.jpg'
            </when>
            <otherwise>
                #{image}
            </otherwise>
        </choose>,#{deptId},#{entryDate},#{job},#{salary},#{phone},NOW(),NOW())
    </insert>
2.3.2修改信息/根据id获取信息

问题描述:在修改员工信息时,需要进行查询回显,但是员工信息涉及两个表 emp 和 emp_expr ,所以这时Sql语句需要对结果进行映射,并封装在Emp类中

Emp类:

@Data
@NoArgsConstructor
@AllArgsConstructor
// ... existing code ...
public class Emp {
    private Integer id;
    private String username;
    private String password;
    private String name;
    private Integer gender; //1.男 2.女
    private String phone;
    private Integer job;
    private Integer salary;
    private String image;
    private MultipartFile file;
    private LocalDate entryDate;
    private Integer deptId; //1.学工部 2.教研部 3.咨询部 4.就业部 5.人事部 6.行政部
    private LocalDateTime createTime;
    private LocalDateTime updateTime;
    //封装员工工作经历
    private List<EmpExpr>exprList ;

    //封装部门名称
    private  String deptName;
}

Empexpr类:

@Data
@NoArgsConstructor
@AllArgsConstructor
public class EmpExpr {
    private Integer id;
    private Integer empId;//对应员工id
    private LocalDate begin;
    private LocalDate end;
    private String company;
    private String job;
}

SQL语句

    <!--自定义映射结果集ResultMap-->
    <resultMap id="empResultMap" type="org.example.pojo.Emp">
        <id column="id" property="id" />
        <result column="username" property="username" />
        <result column="password" property="password" />
        <result column="name" property="name" />
        <result column="gender" property="gender" />
        <result column="phone" property="phone" />
        <result column="job" property="job" />
        <result column="salary" property="salary" />
        <result column="image" property="image" />
        <result column="entry_date" property="entryDate" />
        <result column="dept_id" property="deptId" />
        <result column="create_time" property="createTime" />
        <result column="update_time" property="updateTime" />

        <!--封装exprList-->
        <collection property="exprList" ofType="org.example.pojo.EmpExpr">
            <id column="ee_id" property="id"/>
            <result column="ee_company" property="company"/>
            <result column="ee_job" property="job"/>
            <result column="ee_begin" property="begin"/>
            <result column="ee_end" property="end"/>
            <result column="ee_empid" property="empId"/>
        </collection>
    </resultMap>

    <!--根据ID查询员工的详细信息-->
    <select id="get" resultMap="empResultMap">
        select e.*,
               ee.id ee_id,
               ee.emp_id ee_empid,
               ee.begin ee_begin,
               ee.end ee_end,
               ee.company ee_company,
               ee.job ee_job
        from emp e left join emp_expr ee on e.id = ee.emp_id
        where e.id = #{id}
    </select>

3.员工信息统计

3.1SQL应用

问题描述:统计各职位员工人数

接口文档响应数据示例:

{
  "code": 1,
  "msg": "success",
  "data": {
    "jobList": ["教研主管","学工主管","其他","班主任","咨询师","讲师"],
    "dataList": [1,1,2,6,8,13]
  }
}

由图中可见,返回的是两个列表,但是职位在emp表中记录的是数字(前端选择后返回数字),所以需要对emp表中的职位进行映射。

<select id="exportEmpJobData" resultType="java.util.Map">
        select
            (case job when 1 then '班主任'
                      when 2 then '讲师'
                      when 3 then '学工主管'
                      when 4 then '教研主管'
                      when 5 then '咨询师'
                      else '其他' end)  pos,
            count(*) total
        from emp group by job
        order by total
    </select>

出于简化考虑,结果用Map<>进行封装

List<Map<String,Object>> exportEmpJobData();

注:Mybatis在将结果封装进map时为

    Map<String,Object> map = new HashMap<>();
        map.put("pos",pos1);
        map.put("total",total1);
        list.add(map);

在使用时,使用stream流

//封装jobList
        List<Map<String,Object>> jobDataList = reportMapper.exportEmpJobData();
        List<String> jobList = jobDataList.stream().map(x -> x.get("pos").toString()).toList();
        List<Object> dataList = jobDataList.stream().map(x -> x.get("total")).toList();

4.班级管理

4.1自定义异常

问题描述:在班级管理模块的删除功能中,当班级中仍有人时,该班级无法删除,此时需要自定义异常提醒前端操作

自定义异常类:

public class ClazzDeleteWithStuException extends RuntimeException {

    public ClazzDeleteWithStuException(String message) {
        super(message);
    }
}

异常类使用(ClazzServiceImpl):

    @Override
    public void remove(Integer id) {
        if(studentMapper.countByClazzId(id) > 0) {
            throw new ClazzDeleteWithStuException("该班级仍有学生 不可删除");
        }
        clazzMapper.deleteById(id);
    }

异常捕获(全局异常处理器GlobalExceptionHandler):

    @ExceptionHandler
    public Result handleClazzDeleteWithStuException(ClazzDeleteWithStuException e) {
        log.error(e.getMessage());
        return Result.error(e.getMessage());
    }

5.学员管理,班级信息统计-略

该部分业务与前面逻辑重复,故略过


复盘一下感觉没多少东西,仍需继续努力QAQ

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值