Java阶段四03

第4章-第3节

一、知识点

Mybatis-Plus、mapstruct

二、目标

  • 理解为什么要过滤敏感字段

  • 如何使用查询过滤

  • Mybatis-Plus如何使用联表分页查询

  • 如何实现字段的自动填充

三、内容分析

  • 重点

    • 掌握几种过滤敏感字段的方式

    • 掌握Mybatis-Plus的联表分页查询方式

    • 掌握字段自动填充的实现

  • 难点

    • 掌握几种过滤敏感字段的方式

    • 掌握Mybatis-Plus的联表分页查询方式

    • 掌握字段自动填充的实现

四、内容

1、过滤敏感字段

有的时候有一些敏感数据不方便发给前端,比如用户的密码信息、一些不需要的字段、不能给前端看的数据字段,这个时候这种字段就需要过滤一下

1.1 创建一个要返回给前端的数据实体
java 复制代码
@Data
@AllArgsConstructor
@NoArgsConstructor
public class StudentVo {
    private Long id;
    private String name;
    private Integer sex;
    private Integer age;
    private Long classId;
    // 在这边 我们认为下面的几个字段是不需要给前端的,将其取消掉
    // 代码中不用写,这边只是为了突出不要的是这几个字段
    // private Date createTime;
    // private String createBy;
    // private Date updateTime;
    // private String updateBy;
    // private Integer delFlag;
}
​
1.2 传统方法
java 复制代码
@GetMapping("/list")
public List<StudentVo> queryList() {
    Page<Student> studentPage = new Page<>(1, 5);
    Page<Student> page = service.page(studentPage);
    List<Student> students = page.getRecords();
    List<StudentVo> studentVos = new ArrayList<>();
    // 循环对象集合,对需要保存的字段进行赋值加入集合
    for (Student s : students) {
        StudentVo s2 = new StudentVo();
        s2.setName(s.getName());
        s2.setClassId(s.getClassId());
        s2.setSex(s.getSex());
        // 可以发现,如果字段很多那么这个操作很繁琐
        studentVos.add(s2);
    }
    return studentVos;
}
1.2 使用BeanUtils
java 复制代码
@GetMapping("/list")
public List<StudentVo> queryList() {
    Page<Student> studentPage = new Page<>(1, 5);
    Page<Student> page = service.page(studentPage);
    List<Student> students = page.getRecords();
    List<StudentVo> studentVos = new ArrayList<>();
    // 循环对象集合,对需要保存的字段进行赋值加入集合
    for (Student s : students) {
        StudentVo s2 = new StudentVo();
        // 简化操作,但是效率比较低
        BeanUtils.copyProperties(s,s2);
        studentVos.add(s2);
    }
    return studentVos;
}
1.3 使用插件 mapstruct
1.3.1 导入依赖
java 复制代码
<dependency>
    <groupId>org.mapstruct</groupId>
    <artifactId>mapstruct</artifactId>
    <version>1.4.2.Final</version>
</dependency>
<dependency>
    <groupId>org.mapstruct</groupId>
    <artifactId>mapstruct-processor</artifactId>
    <version>1.4.2.Final</version>
</dependency>
1.3.2 建一个专门用于映射的文件夹mapping
java 复制代码
@Mapper
public interface StudentMapping {
    StudentMapping INSTANCE = Mappers.getMapper(StudentMapping.class);
    StudentVo toStudentVo(Student student);
}
1.3.3 使用
java 复制代码
@GetMapping("/list")
public List<StudentVo> queryList() {
    Page<Student> studentPage = new Page<>(1, 5);
    Page<Student> page = service.page(studentPage);
    List<Student> students = page.getRecords();
    List<StudentVo> studentVos = new ArrayList<>();
    // 循环对象集合,对需要保存的字段进行赋值加入集合
    for (Student s : students) {
        StudentVo s2 = StudentMapping.INSTANCE.toStudentVo(s);
        studentVos.add(s2);
    }
    return studentVos;
}
1.3.4 也可以直接处理list
java 复制代码
@Mapper
public interface StudentMapping {
    StudentMapping INSTANCE = Mappers.getMapper(StudentMapping.class);
    StudentVo toStudentVo(Student student);
    List<StudentVo> toStudentVoList(List<Student> studentList);
}
java 复制代码
@GetMapping("/list")
public List<StudentVo> queryList() {
    Page<Student> studentPage = new Page<>(1, 5);
    Page<Student> page = service.page(studentPage);
    List<Student> students = page.getRecords();
    List<StudentVo> studentVos = StudentMapping.INSTANCE.toStudentVoList(students);
    return studentVos;
}
1.3.5 通过配置自动生成的方法来映射字段
java 复制代码
@Mappings({
    @Mapping(source = "money", target = "studentMoney")
})
MsStudentVo msStudentToMsStudentVo(MsStudent msStudent);

2、联表分页查询

查询每个班级的学生 -> 查询每个班级,以及这个班级的学生数量

2.1 创建要返回的数据的实体类
java 复制代码
@Data
public class ClassStudentVo {
    private Long id;
    private String name;
    private List<Student> studentList;
}
2.2 创建ClassMapper
java 复制代码
@Repository
public interface ClassMapper extends BaseMapper<ClassStudentVo> {
    // 由于Mybatis本身没有联表查询的操作,所以我们要自己手写一个方法来实现
    Page<ClassStudentVo> queryClassAndStudent(@Param("page") Page<ClassStudentVo> page,@Param(Constants.WRAPPER) Wrapper<ClassStudentVo> wrapper);
}
复制代码
2.3 接口中创建方法
java 复制代码
public interface IClassService extends IService<ClassStudentVo> {
    Page<ClassStudentVo> queryClassAndStudent(Page<ClassStudentVo> page, Wrapper<ClassStudentVo> wrapper);
}
2.4 实现类重写方法
java 复制代码
@Service
public class ClassService extends ServiceImpl<ClassMapper, ClassStudentVo> implements IClassService {
    @Autowired
    private ClassMapper mapper;
​
    @Override
    public Page<ClassStudentVo> queryClassAndStudent(Page<ClassStudentVo> page, Wrapper<ClassStudentVo> wrapper) {
        return mapper.queryClassAndStudent(page, wrapper);
    }
}
2.5 两种实现方式
集中式

ClassController.java

java 复制代码
@GetMapping("/queryClassAndStudent")
public List<ClassStudentVo> queryAll(ClassStudentVo classStudentVo) {
    Page<ClassStudentVo> classPage = new Page<>(1, 5);
    QueryWrapper<ClassStudentVo> wrapper = new QueryWrapper<>();
    wrapper.eq(StringUtils.isNotEmpty(classStudentVo.getId()), "c.id", classStudentVo.getId());
    
    Page<ClassStudentVo> page = service.queryClassAndStudent(classPage, wrapper);
    System.out.println(page.getTotal());
    return page.getRecords();
}

classMapper.xml

java 复制代码
<!--  配置关联  -->
<resultMap id="classStudentVoRes" type="com.example.demo.entity.vo.ClassStudentVo">
    <id property="id" column="id"/>
    <result property="name" column="name"/>
    <collection property="studentList" ofType="com.example.demo.entity.Student" autoMapping="true">
        <id property="id" column="studentId"/>
        <result property="name" column="studentName"/>
        <result property="age" column="age"/>
    </collection>
</resultMap>
<!--  查询语句  -->
<select id="queryClassAndStudent" resultMap="classStudentVoRes">
    SELECT c.id,
    c.name,
    s.id studentId,
    s.name studentName,
    s.sex,
    s.age,
    s.class_id
    FROM class c
    LEFT JOIN student s on c.id = s.class_id
    <!-- ${ew.customSqlSegment}这个是固定写法一定要加,不然条件就无效了 -->
    ${ew.customSqlSegment}
</select>
分布式

ClassController.java

java 复制代码
@GetMapping("/queryClassAndStudent2")
public List<ClassStudentVo> queryAll2(ClassStudentVo classStudentVo) {
    Page<ClassStudentVo> classPage = new Page<>(1, 5);
    QueryWrapper<ClassStudentVo> wrapper = new QueryWrapper<>();
    wrapper.eq(StringUtils.isNotEmpty(classStudentVo.getId()), "id", classStudentVo.getId());
    Page<ClassStudentVo> page = service.queryClassAndStudent(classPage, wrapper);
    System.out.println(page.getTotal());
    return page.getRecords();
}

classMapper.xml

java 复制代码
<!--  配置关联  -->
<resultMap id="classStudentVoRes" type="com.example.demo.entity.vo.ClassStudentVo">
    <id property="id" column="id"/>
    <!--            <result property="name" column="name"/>-->
    <collection property="studentList"
                ofType="com.example.demo.entity.Student"
                select="getStudentsByClassId"
                column="{classId=id}"/>
</resultMap>
<!--  班级的查询  -->
<select id="queryClassAndStudent" resultMap="classStudentVoRes">
    SELECT id,name FROM class
    <!-- ${ew.customSqlSegment}这个是固定写法一定要加,不然条件就无效了 -->
    ${ew.customSqlSegment}
</select>
<!--  内部的子查询  -->
<select id="getStudentsByClassId" resultType="com.example.demo.entity.Student">
    SELECT id, name, sex, age, class_id
    FROM student
    WHERE class_id = #{classId}
</select>

3、字段自动填充

3.1 字段注解
java 复制代码
@TableField(fill = FieldFill.INSERT)
private Date createTime;
​
@TableField(fill = FieldFill.INSERT_UPDATE)
private Date updateTime;
3.2 封装一个填充类
java 复制代码
@Component
public class FieldHandler implements MetaObjectHandler {
    /**
     * 插入时的填充策略
     *
     * @param metaObject
     */
    @Override
    public void insertFill(MetaObject metaObject) {
        this.setFieldValByName("createTime", new Date(), metaObject);
        this.setFieldValByName("updateTime", new Date(), metaObject);
    }
​
    /**
     * 更新时的填充策略
     *
     * @param metaObject
     */
    @Override
    public void updateFill(MetaObject metaObject) {
        this.setFieldValByName("updateTime", new Date(), metaObject);
    }
​
}
3.3 执行对应的语句即可

4、小结

本章节中我们学习了Mybatis-Plus的联表分页查询、字段的自动填充和敏感字段的过滤,对Mybatis-Plus的操作更加得心应手,课后再通过练习进行巩固彻底掌握Mybatis-Plus的使用。

下一节中我们将会学到项目中会用到的插件-jwt,了解什么是CSRF攻击手段,学习如何防范、掌握真实项目中的登录流程。

相关推荐
慢慢成长的码农2 分钟前
Kotlin 常量定义
开发语言·数据库·kotlin
THE WHY3 分钟前
IDEA Maven构建时报错:无效的目标发行版17
java·后端·jdk·maven·intellij-idea
白露与泡影16 分钟前
Spring Boot性能提升的核武器,速度提升500%!
java·spring boot·后端
昔我往昔19 分钟前
Spring Boot中的依赖注入是如何工作
java·spring boot·后端
Eiceblue21 分钟前
Python在Excel工作表中创建数据透视表
开发语言·python·visualstudio·excel
2401_8582861139 分钟前
124.【C语言】数据结构之快速排序的小区间优化和非递归的解决方法
c语言·开发语言·数据结构·算法·排序算法·
Spcarrydoinb44 分钟前
python学习笔记—17—数据容器之字符串
笔记·python·学习
编程小筑44 分钟前
TypeScript语言的网络编程
开发语言·后端·golang
无名3871 小时前
FreeSWITCH rtp session 的初始化
java·服务器·前端
老大白菜1 小时前
第6章:Go语言并发编程
开发语言·后端·golang