MapStruct初窥门径

news2024/11/17 11:42:39

一、介绍

MapStruct相比于BeanUtils性能更高,能够实现DO,DTO,VO之间的转换,达到解耦合的目的

二、使用前提

  1. 添加依赖
		<dependency>
            <groupId>org.mapstruct</groupId>
            <artifactId>mapstruct</artifactId>
            <version>1.5.5.Final</version>
        </dependency>
        <dependency>
            <groupId>org.mapstruct</groupId>
            <artifactId>mapstruct-processor</artifactId>
            <version>1.5.5.Final</version>
            <scope>provided</scope>
        </dependency>
  1. 新建一个接口StudentConvert,实现不同POJO之间的转换
  • 接口中需要使用MapStruct的一个注解@Mapper,利用MapStruct的工厂创建一个studentConvert类,可以通过该类调用类中的方法
  1. 新建DO,DTO,VO类
  • DO
@Data
@AllArgsConstructor
@NoArgsConstructor
public class StudentDO {

    private Integer id;

    private String name;

    private String password;

    private String phoneNumber;

    private Integer gender;
    
    private Double price;
    
    private Date birthDay;
    
    private SubjectDO subjectDO;

}
@Data
public class SubjectDO {

    private Integer id;

    private String name;
}
  • DTO
@Data
@AllArgsConstructor
@NoArgsConstructor
public class StudentDTO {

    private Integer id;

    private String studentName;

    private String phoneNumber;

    private String gender;
    
    private String price;
    
    private String birthDay;
    
    private SubjectDTO subjectDTO;

}
@Data
public class SubjectDTO {

    private Integer subjectId;

    private String subjectName;
}
  • VO
@Data
@AllArgsConstructor
@NoArgsConstructor
public class StudentVO {

    private Integer id;

    private String studentName;

    private Boolean hasPhoneNumber;

    private String gender;
}

三、使用示例

1.DO 转 DTO

  • 转换逻辑
@Mapper
public interface StudentConvert {

    StudentConvert INSTANCE = Mappers.getMapper(StudentConvert.class);

    /**
     * DO convert to DTO
     * @param studentDO StudentDO
     * @return com.haomiao.algorithm.pojo.StudentDTO
     */
    StudentDTO doToDto(StudentDO studentDO);
}
  • 进行测试
	@Test
    void doConvertDto(){
        StudentDO studentDO = buildStudentDO();
        StudentDTO studentDTO = StudentConvert.INSTANCE.doToDto(studentDO);
        System.out.println(studentDTO);
    }
    
	StudentDO buildStudentDO(){
        StudentDO studentDO = new StudentDO();
        studentDO.setId(1);
        studentDO.setName("zhangsan");
        studentDO.setPassword("Qw123");
        studentDO.setPhoneNumber("15271861495");
        studentDO.setGender(1);
        studentDO.setPrice(22.1234d);
        studentDO.setBirthDay(new Date());
        studentDO.setSubjectDO(buildSubjectDO());
        return studentDO;
    }
    
    SubjectDO buildSubjectDO(){
        SubjectDO subjectDO = new SubjectDO();
        subjectDO.setId(12);
        subjectDO.setName("数学");
        return subjectDO;
    }
    
  • 输出结果为:
StudentDTO(id=1, name=null, phoneNumber=15271861495, gender=1, birthDay=23-10-4 下午5:25, price=22.1234, subjectDTO=null)

因此得出结论:

  1. 同类型同名的属性会自动映射
  2. 就算不是同类型,也会自动进行类型转换
  • 8种基本类型及其对应的包装类型之间会自动转换
  • 8种基本类型(及其对应的包转类型)和String会自动转换
  • 日期类型和String之间会自动转换

四、@Mappings注解

@Mappings由多个@Mapping注解组成

作用:自定义映射

1.小数格式化

注意使用numberFormat时,小数转换为小数是不行的

  • 将Double类型保留两位小数,映射为String类型
	@Mappings(
            @Mapping(source = "price",target = "price",numberFormat = "#.00")
    )
    StudentDTO doToDto(StudentDO studentDO);
  • 输出结果为:
StudentDTO(id=1, name=null, phoneNumber=15271861495, gender=1, birthDay=23-10-4 下午5:51, price=22.12, subjectDTO=null)

2.时间格式化
  • 使用dateFormat
	@Mappings(
            value = {
                    @Mapping(source = "price",target = "price",numberFormat = "#.00"),
                    @Mapping(source = "birthDay",target = "birthDay",dateFormat = "yyyy-MM-dd HH:mm:ss")
            }
    )
    StudentDTO doToDto(StudentDO studentDO);
  • 输出结果为:
StudentDTO(id=1, name=null, phoneNumber=15271861495, gender=1, birthDay=2023-10-04 17:57:22, price=22.12, subjectDTO=null)
3.忽略某个属性映射
  • 使用ignore
@Mappings(
            value = {
                    @Mapping(source = "price",target = "price",numberFormat = "#.00"),
                    @Mapping(source = "birthDay",target = "birthDay",dateFormat = "yyyy-MM-dd HH:mm:ss"),
                    @Mapping(target = "phoneNumber",ignore = true)
            }
    )
    StudentDTO doToDto(StudentDO studentDO);
  • 输出结果为:
StudentDTO(id=1, name=null, phoneNumber=null, gender=1, birthDay=2023-10-04 18:02:17, price=22.12, subjectDTO=null)

4.名称不同映射
@Mappings(
            value = {
                    @Mapping(source = "price",target = "price",numberFormat = "#.00"),
                    @Mapping(source = "birthDay",target = "birthDay",dateFormat = "yyyy-MM-dd HH:mm:ss"),
                    @Mapping(target = "phoneNumber",ignore = true),
                    @Mapping(source = "name",target = "studentName")
            }
    )
    StudentDTO doToDto(StudentDO studentDO);
  • 输出结果为:
StudentDTO(id=1, studentName=zhangsan, phoneNumber=null, gender=1, birthDay=2023-10-04 18:16:04, price=22.12, subjectDTO=null)
5.复杂类型转换
  • 在转换方法中,对复杂类型再添加一个转换规则,如下:
@Mapper
public interface StudentConvert {

    StudentConvert INSTANCE = Mappers.getMapper(StudentConvert.class);

    /**
     * DO convert to DTO
     * @param studentDO StudentDO
     * @return com.haomiao.algorithm.pojo.StudentDTO
     */
    @Mappings(
            value = {
                    @Mapping(source = "price",target = "price",numberFormat = "#.00"),
                    @Mapping(source = "birthDay",target = "birthDay",dateFormat = "yyyy-MM-dd HH:mm:ss"),
                    @Mapping(target = "phoneNumber",ignore = true),
                    @Mapping(source = "name",target = "studentName"),
                    @Mapping(source = "subjectDO",target = "subjectDTO")
            }
    )
    StudentDTO doToDto(StudentDO studentDO);

    /**
     * DO convert to DTO
     * @param subjectDO SubjectDO
     * @return com.haomiao.algorithm.pojo.SubjectDTO
     */
    @Mapping(source = "id",target = "subjectId")
    @Mapping(source = "name",target = "subjectName")
    SubjectDTO subjectDo2SubjectDto(SubjectDO subjectDO);
}
  • 输出结果为:
StudentDTO(id=1, studentName=zhangsan, phoneNumber=null, gender=1, birthDay=2023-10-04 18:27:28, price=22.12, subjectDTO=SubjectDTO(subjectId=12, subjectName=数学))

  • 可以观察生成的代码
    在这里插入图片描述
6.MapStruct规则无法映射,自定义映射规则
  • 使用@AfterMapping和@MappingTarget注解

注意:这种使用场景需要自己实现方法逻辑,因此需要转换的类为抽象类,而非接口,之前的案例使用接口实现,这里可以参考别人的抽象类实现:

在这里插入图片描述

7.批量转换

在这里插入图片描述

8.BeanMapping使用(适用于只需要映射少量字段的情况)

在这里插入图片描述

9.InheritConfigration

在这里插入图片描述

10.反向继承
  • 注意:只会继承@Mapping注解,不会继承BeanMapping注解
    在这里插入图片描述
11.结合Spring

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1060193.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

第八章 Linux文件系统权限

目录 8.1 文件的一般权限 1.修改文件或目录的权限---chmod命令 2.对于文件和目录&#xff0c;r&#xff0c;w&#xff0c;x有不同的作用&#xff1a; 3.修改文件或目录的所属主和组---chown,chgrp 8.2 文件和目录的特殊权限 三种通过字符描述文件权限 8.3 ACL 权限 1.A…

基于Java的药店管理系统设计与实现(源码+lw+部署文档+讲解等)

文章目录 前言具体实现截图论文参考详细视频演示为什么选择我自己的网站自己的小程序&#xff08;小蔡coding&#xff09;有保障的售后福利 代码参考源码获取 前言 &#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师、全栈领域优质创作…

1500*A. Boredom(DP)

Problem - 455A - Codeforces Boredom - 洛谷 解析&#xff1a; 首先统计每个数的个数&#xff0c;并且统计出最大值mx。 问题转换为&#xff0c;从1-mx 中选择任意个数字&#xff0c;使其都不相邻&#xff0c;求最大的总和。 开始没有思路&#xff0c;以为直接选取偶数位和奇…

项目进展(七)-焊接ADS1285及其外围电路,学习芯片的SPI部分

一、焊接芯片及其外围电路 总体焊接过程没有出现什么大问题&#xff0c;也算顺利&#xff0c;下一步主要是根据SPI来编写代码&#xff0c;配置该芯片。 焊接之后的PCB如下(手工焊接&#xff0c;比较丑陋&#xff0c;哈哈哈哈) 之后测试了4.096V参考电压和晶振输出&#xff0c…

CART算法解密:从原理到Python实现

目录 一、简介CART算法的背景例子&#xff1a;医疗诊断 应用场景例子&#xff1a;金融风控 定义与组成例子&#xff1a;电子邮件分类 二、决策树基础什么是决策树例子&#xff1a;天气预测 如何构建简单的决策树例子&#xff1a;动物分类 决策树算法的类型例子&#xff1a;垃圾…

长时序栅格数据缺失值插补

长时序栅格数据经常会出现一些缺失值&#xff0c;会对后续的分析造成很大的不便。这便需要利用一些插值算法对这些缺失数据进行填补&#xff0c;奇异谱分析&#xff08;SSA&#xff09;便是常用的一种插值方法。更多内容可见公众号GeodataAnalysis。 简介 在时间序列分析中&a…

处理机调度的概念,层次联系以及七状态模型

1.基本概念 当有一堆任务要处理&#xff0c;但由于资源有限&#xff0c;这些事情没法同时处理。 这就需要确定某种规则来决定处理这些任务的顺序&#xff0c;这就是“调度”研究的问题。 2. 三个层次 1.高级调度&#xff08;作业调度&#xff09; 高级调度&#xff08;作业…

websocket逆向【python实现websocket拦截】

python实现websocket拦截 前言一、拦截的优缺点优点:缺点:二、实现方法1.环境配置2.代码三、总结前言 开发者工具F12,筛选ws后,websocket的消息是这样显示的,如何获取这里面的消息呢? 以下是本篇文章正文内容 一、拦截的优缺点 主要讲解一下websocket拦截的实现,现在…

结构和基本尺寸

声明 本文是学习GB-T 586-2015 船用法兰铸钢止回阀. 而整理的学习笔记,分享出来希望更多人受益,如果存在侵权请及时联系我们 1 范围 本标准规定了法兰连接尺寸和密封面按 CB/T 4196、GB/T 2501 的船用法兰铸钢止回阀(以下简 称止回阀)的分类和标记、要求、试验方法、检验规…

sheng的学习笔记-【中英】【吴恩达课后测验】Course 1 - 神经网络和深度学习 - 第四周测验

课程1_第4周_测验题 目录&#xff1a;目录 第一题 1.在我们的前向传播和后向传播实现中使用的 “缓存” 是什么&#xff1f; A. 【  】它用于在训练期间缓存成本函数的中间值。 B. 【  】我们用它将在正向传播过程中计算的变量传递到相应的反向传播步骤。它包含了反向传…

Linux系统编程系列之条件变量

一、什么是条件变量 条件变量是一种同步互斥机制&#xff0c;通常与互斥锁一起使用以实现线程之间的通信和同步。 二、问题的引入 先来看一个例子:小楠是一名在校学生&#xff0c;每个月都会从父母那里得到一笔生活费。现在她的钱花光了&#xff0c;想要去取钱。但是很显然取钱…

Redis-缓存穿透,缓存击穿,缓存雪崩

缓存穿透&#xff0c;缓存击穿&#xff0c;缓存雪崩 缓存穿透处理方案解决方案1 缓存空数据解决方案2 布隆过滤器 缓存击穿处理方案解决方案 1 互斥锁解决方案2 逻辑过期 缓存雪崩处理方案解决方案 1 给不同的key的过期时间设置添加一个随机值&#xff0c;降低同一个时段大量ke…

柯桥生活口语学习,英语中初次见面,除了Nice to meet you,还能说什么?

第一印象非常重要。所以当你第一次见到某人时&#xff0c;留下一个好印象很重要&#xff0c;尤其是当你面对一个重要的工作或者面对某个对你来说可能非常特别的人时。 下面我列出了一些最常用的说“很高兴见到你”的表达方法&#xff0c;也包括对方的回答&#xff0c;除了nice …

活动报名与缴费小程序开发笔记一

项目背景 活动报名与缴费小程序的开发背景主要源于以下几个因素&#xff1a; 1.数字化时代的需求&#xff1a; 随着移动互联网和智能手机的普及&#xff0c;人们习惯使用手机进行各种活动。传统的纸质报名表格和线下缴费方式变得相对繁琐&#xff0c;而数字化报名与缴费小程序…

2023年-华为机试题库B卷(Python)【满分】

华为机试题库B卷 已于5月10号 更新为2023 B卷 &#xff08;2023-10-04 更新本文&#xff09; 华为机试有三道题目&#xff0c;前两道属于简单或中等题&#xff0c;分值为100分&#xff0c;第三道为中等或困难题&#xff0c;分值为200分。总分为 400 分&#xff0c;150分钟考试…

GKR+Groth16:更快的MiMC证明

1. 引言 Consensys团队Alexandre Belling等人2022年论文 Recursion over Public-Coin Interactive Proof Systems; Faster Hash Verification 中&#xff0c;提出了&#xff1a; 用GKR来证明MiMC哈希计算的完整性将GKR verifier嵌入到SNARK&#xff08;Groth16&#xff09;电…

【开发篇】十四、SpringBoot整合Quartz实现定时任务

文章目录 1、关于定时任务2、Java原生实现3、相关名词4、SpringBoot整合Quartz5、Quartz的通用配置6、关于QuartzJobBean7、关于调度器Scheduler的绑定8、Quartz持久化 1、关于定时任务 定时任务在实际开发中使用场景很多&#xff0c;比如&#xff1a; 年度报告各种统计报告某…

vs code 离线安装 CodeLLDB 包[Acquiring CodeLLDB platform package]

1. 问题描述 最近在配置使用vscode编译c&#xff0c;一打开vscode就弹出以下信息“Acquiring CodeLLDB platform package” 2. 问题原因 vscode在安装CodeLLDB插件时&#xff0c;速度太慢&#xff0c;一直不能成功 3. 解决方案&#xff1a; 离线下载 CodeLLDB插件&#xff0c…

前后端通信到底是怎样一个过程

前后端通信是怎样 前言&#xff1a;Http协议 超文本传输协议 规定&#xff1a;每一次前后端通信&#xff0c;前端需要主动向后端发出请求&#xff0c;后端接收到前端的请求后&#xff0c;可以给出响应 1、Http报文 浏览器向服务器发送请求时&#xff0c;请求本身就是信息&…