Java阶段四03

[复制链接]
发表于 2025-1-11 11:14:18 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
第4章-第3节

一、知识点

Mybatis-Plus、mapstruct
二、目标



  • 明白为什么要过滤敏感字段
  • 如何使用查询过滤
  • Mybatis-Plus如何使用联表分页查询
  • 如何实现字段的自动填充
三、内容分析



  • 重点

    • 掌握几种过滤敏感字段的方式
    • 掌握Mybatis-Plus的联表分页查询方式
    • 掌握字段自动填充的实现

  • 难点

    • 掌握几种过滤敏感字段的方式
    • 掌握Mybatis-Plus的联表分页查询方式
    • 掌握字段自动填充的实现

四、内容

1、过滤敏感字段

有的时候有一些敏感数据不方便发给前端,好比用户的密码信息、一些不须要的字段、不能给前端看的数据字段,这个时候这种字段就须要过滤一下
1.1 创建一个要返回给前端的数据实体

  1. @Data
  2. @AllArgsConstructor
  3. @NoArgsConstructor
  4. public class StudentVo {
  5.    private Long id;
  6.    private String name;
  7.    private Integer sex;
  8.    private Integer age;
  9.    private Long classId;
  10.    // 在这边 我们认为下面的几个字段是不需要给前端的,将其取消掉
  11.    // 代码中不用写,这边只是为了突出不要的是这几个字段
  12.    // private Date createTime;
  13.    // private String createBy;
  14.    // private Date updateTime;
  15.    // private String updateBy;
  16.    // private Integer delFlag;
  17. }
复制代码
1.2 传统方法

  1. @GetMapping("/list")
  2. public List<StudentVo> queryList() {
  3.    Page<Student> studentPage = new Page<>(1, 5);
  4.    Page<Student> page = service.page(studentPage);
  5.    List<Student> students = page.getRecords();
  6.    List<StudentVo> studentVos = new ArrayList<>();
  7.    // 循环对象集合,对需要保存的字段进行赋值加入集合
  8.    for (Student s : students) {
  9.        StudentVo s2 = new StudentVo();
  10.        s2.setName(s.getName());
  11.        s2.setClassId(s.getClassId());
  12.        s2.setSex(s.getSex());
  13.        // 可以发现,如果字段很多那么这个操作很繁琐
  14.        studentVos.add(s2);
  15.    }
  16.    return studentVos;
  17. }
复制代码
1.2 使用BeanUtils

  1. @GetMapping("/list")
  2. public List<StudentVo> queryList() {
  3.    Page<Student> studentPage = new Page<>(1, 5);
  4.    Page<Student> page = service.page(studentPage);
  5.    List<Student> students = page.getRecords();
  6.    List<StudentVo> studentVos = new ArrayList<>();
  7.    // 循环对象集合,对需要保存的字段进行赋值加入集合
  8.    for (Student s : students) {
  9.        StudentVo s2 = new StudentVo();
  10.        // 简化操作,但是效率比较低
  11.        BeanUtils.copyProperties(s,s2);
  12.        studentVos.add(s2);
  13.    }
  14.    return studentVos;
  15. }
复制代码
1.3 使用插件 mapstruct

1.3.1 导入依赖

  1. <dependency>
  2.    <groupId>org.mapstruct</groupId>
  3.    <artifactId>mapstruct</artifactId>
  4.    <version>1.4.2.Final</version>
  5. </dependency>
  6. <dependency>
  7.    <groupId>org.mapstruct</groupId>
  8.    <artifactId>mapstruct-processor</artifactId>
  9.    <version>1.4.2.Final</version>
  10. </dependency>
复制代码
1.3.2 建一个专门用于映射的文件夹mapping

  1. @Mapper
  2. public interface StudentMapping {
  3.    StudentMapping INSTANCE = Mappers.getMapper(StudentMapping.class);
  4.    StudentVo toStudentVo(Student student);
  5. }
复制代码
1.3.3 使用

  1. @GetMapping("/list")
  2. public List<StudentVo> queryList() {
  3.    Page<Student> studentPage = new Page<>(1, 5);
  4.    Page<Student> page = service.page(studentPage);
  5.    List<Student> students = page.getRecords();
  6.    List<StudentVo> studentVos = new ArrayList<>();
  7.    // 循环对象集合,对需要保存的字段进行赋值加入集合
  8.    for (Student s : students) {
  9.        StudentVo s2 = StudentMapping.INSTANCE.toStudentVo(s);
  10.        studentVos.add(s2);
  11.    }
  12.    return studentVos;
  13. }
复制代码
1.3.4 也可以直接处理list

  1. @Mapper
  2. public interface StudentMapping {
  3.    StudentMapping INSTANCE = Mappers.getMapper(StudentMapping.class);
  4.    StudentVo toStudentVo(Student student);
  5.    List<StudentVo> toStudentVoList(List<Student> studentList);
  6. }
复制代码
  1. @GetMapping("/list")
  2. public List<StudentVo> queryList() {
  3.    Page<Student> studentPage = new Page<>(1, 5);
  4.    Page<Student> page = service.page(studentPage);
  5.    List<Student> students = page.getRecords();
  6.    List<StudentVo> studentVos = StudentMapping.INSTANCE.toStudentVoList(students);
  7.    return studentVos;
  8. }
复制代码
1.3.5 通过设置自动生成的方法来映射字段

  1. @Mappings({
  2.    @Mapping(source = "money", target = "studentMoney")
  3. })
  4. MsStudentVo msStudentToMsStudentVo(MsStudent msStudent);
复制代码

2、联表分页查询

   查询每个班级的学生 -> 查询每个班级,以及这个班级的学生数量
  2.1 创建要返回的数据的实体类

  1. @Data
  2. public class ClassStudentVo {
  3.    private Long id;
  4.    private String name;
  5.    private List<Student> studentList;
  6. }
复制代码
2.2 创建ClassMapper

  1. @Repository
  2. public interface ClassMapper extends BaseMapper<ClassStudentVo> {
  3.    // 由于Mybatis本身没有联表查询的操作,所以我们要自己手写一个方法来实现
  4.    Page<ClassStudentVo> queryClassAndStudent(@Param("page") Page<ClassStudentVo> page,@Param(Constants.WRAPPER) Wrapper<ClassStudentVo> wrapper);
  5. }
复制代码
复制代码
2.3 接口中创建方法

  1. public interface IClassService extends IService<ClassStudentVo> {
  2.    Page<ClassStudentVo> queryClassAndStudent(Page<ClassStudentVo> page, Wrapper<ClassStudentVo> wrapper);
  3. }
复制代码
2.4 实现类重写方法

  1. @Service
  2. public class ClassService extends ServiceImpl<ClassMapper, ClassStudentVo> implements IClassService {
  3.    @Autowired
  4.    private ClassMapper mapper;
  5.    @Override
  6.    public Page<ClassStudentVo> queryClassAndStudent(Page<ClassStudentVo> page, Wrapper<ClassStudentVo> wrapper) {
  7.        return mapper.queryClassAndStudent(page, wrapper);
  8.    }
  9. }
复制代码
2.5 两种实现方式



  • 集中式

           ClassController.java
       
    1. @GetMapping("/queryClassAndStudent")
    2. public List<ClassStudentVo> queryAll(ClassStudentVo classStudentVo) {
    3.    Page<ClassStudentVo> classPage = new Page<>(1, 5);
    4.    QueryWrapper<ClassStudentVo> wrapper = new QueryWrapper<>();
    5.    wrapper.eq(StringUtils.isNotEmpty(classStudentVo.getId()), "c.id", classStudentVo.getId());
    6.    
    7.    Page<ClassStudentVo> page = service.queryClassAndStudent(classPage, wrapper);
    8.    System.out.println(page.getTotal());
    9.    return page.getRecords();
    10. }
    复制代码
          classMapper.xml
       
    1. <!--  配置关联  -->
    2. <resultMap id="classStudentVoRes" type="com.example.demo.entity.vo.ClassStudentVo">
    3.    <id property="id" column="id"/>
    4.    <result property="name" column="name"/>
    5.    <collection property="studentList" ofType="com.example.demo.entity.Student" autoMapping="true">
    6.        <id property="id" column="studentId"/>
    7.        <result property="name" column="studentName"/>
    8.        <result property="age" column="age"/>
    9.    </collection>
    10. </resultMap>
    11. <!--  查询语句  -->
    12. <select id="queryClassAndStudent" resultMap="classStudentVoRes">
    13.    SELECT c.id,
    14.    c.name,
    15.    s.id studentId,
    16.    s.name studentName,
    17.    s.sex,
    18.    s.age,
    19.    s.class_id
    20.    FROM class c
    21.    LEFT JOIN student s on c.id = s.class_id
    22.    <!-- ${ew.customSqlSegment}这个是固定写法一定要加,不然条件就无效了 -->
    23.    ${ew.customSqlSegment}
    24. </select>
    复制代码

  • 分布式

           ClassController.java
       
    1. @GetMapping("/queryClassAndStudent2")
    2. public List<ClassStudentVo> queryAll2(ClassStudentVo classStudentVo) {
    3.    Page<ClassStudentVo> classPage = new Page<>(1, 5);
    4.    QueryWrapper<ClassStudentVo> wrapper = new QueryWrapper<>();
    5.    wrapper.eq(StringUtils.isNotEmpty(classStudentVo.getId()), "id", classStudentVo.getId());
    6.    Page<ClassStudentVo> page = service.queryClassAndStudent(classPage, wrapper);
    7.    System.out.println(page.getTotal());
    8.    return page.getRecords();
    9. }
    复制代码
          classMapper.xml
       
    1. <!--  配置关联  -->
    2. <resultMap id="classStudentVoRes" type="com.example.demo.entity.vo.ClassStudentVo">
    3.    <id property="id" column="id"/>
    4.    <!--            <result property="name" column="name"/>-->
    5.    <collection property="studentList"
    6.                ofType="com.example.demo.entity.Student"
    7.                select="getStudentsByClassId"
    8.                column="{classId=id}"/>
    9. </resultMap>
    10. <!--  班级的查询  -->
    11. <select id="queryClassAndStudent" resultMap="classStudentVoRes">
    12.    SELECT id,name FROM class
    13.    <!-- ${ew.customSqlSegment}这个是固定写法一定要加,不然条件就无效了 -->
    14.    ${ew.customSqlSegment}
    15. </select>
    16. <!--  内部的子查询  -->
    17. <select id="getStudentsByClassId" resultType="com.example.demo.entity.Student">
    18.    SELECT id, name, sex, age, class_id
    19.    FROM student
    20.    WHERE class_id = #{classId}
    21. </select>
    复制代码

3、字段自动填充

3.1 字段注解

  1. @TableField(fill = FieldFill.INSERT)
  2. private Date createTime;
  3. @TableField(fill = FieldFill.INSERT_UPDATE)
  4. private Date updateTime;
复制代码
3.2 封装一个填充类

  1. @Component
  2. public class FieldHandler implements MetaObjectHandler {
  3.    /**
  4.     * 插入时的填充策略
  5.     *
  6.     * @param metaObject
  7.     */
  8.    @Override
  9.    public void insertFill(MetaObject metaObject) {
  10.        this.setFieldValByName("createTime", new Date(), metaObject);
  11.        this.setFieldValByName("updateTime", new Date(), metaObject);
  12.    }
  13.    /**
  14.     * 更新时的填充策略
  15.     *
  16.     * @param metaObject
  17.     */
  18.    @Override
  19.    public void updateFill(MetaObject metaObject) {
  20.        this.setFieldValByName("updateTime", new Date(), metaObject);
  21.    }
  22. }
复制代码
3.3 执行对应的语句即可

4、小结

本章节中我们学习了Mybatis-Plus的联表分页查询、字段的自动填充和敏感字段的过滤,对Mybatis-Plus的操作更加得心应手,课后再通过练习进行巩固彻底掌握Mybatis-Plus的使用。
下一节中我们将会学到项目中会用到的插件-jwt,了解什么是CSRF攻击手段,学习如何防范、掌握真实项目中的登录流程。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
继续阅读请点击广告
回复

使用道具 举报

快速回复 返回顶部 返回列表