MapStruct初窥门径

⚠️注意⚠️

当同时使用MapStruct和Lombok时。一定要在pom文件中指定两个注解的执行顺序

	<build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <annotationProcessorPaths>
                        <path>
                            <groupId>org.mapstruct</groupId>
                            <artifactId>mapstruct-processor</artifactId>
                            <version>${org.mapstruct.version}</version>
                        </path>
                        <path>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                            <version>${lombok.version}</version>
                        </path>
                    </annotationProcessorPaths>
                </configuration>
            </plugin>
        </plugins>
    </build>

一、介绍

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

在这里插入图片描述

  • 注意:如果要使用Spring容器注入,需要删除下面代码
    StudentConvert INSTANCE = Mappers.getMapper(StudentConvert.class);

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值