MapStruct简单使用

前言

平常开发过程中总是会有数据映射转换,比如 DO转DTO,DTO转VO,通常的做法就是get/set方法,实体字段数量很大的时候就会写大量的转换,涉及到每个字段,重复的工作量大,并且很容易在赋值的过程中写错,于是会选择一些第三方的工具类来做对应的转换,如:Spring BeanUtils / Cglib BeanCopier /Apache BeanUtils /Apache PropertyUtils /Dozer,然而这些工具类转换也并不稳妥,有时转换失败了也很难排查问题.

实体转换类选择

各种转换工具类,在实际开发中应该选择哪种?相信很多人在开发中选择Apache BeanUtils, 毕竟是Apache旗下,稳定可靠,可是这个工具类却被阿里开发公约点名了:

阿里开发公约认为该工具类性能差,还推荐了其他的工具类,最后又说是浅拷贝,啥是浅拷贝?
如果属性是基本类型,拷贝的就是基本类型的值;如果属性是内存地址(引用类型),拷贝的就是内存地址 ,因此如果其中一个对象改变了这个地址,就会影响到另一个对象。 就是地址值的指向,也是不靠谱的.

MapStruct 简介

翻开MapStruct官网,描述很清楚:

大致意思是MapStruct是一个代码映射工具,能够保证高效率,并且能让开发人员快速定位到错误,使用了注释处理,能简单接入.

MapStruct 接入与使用

MapStruct 官网给定了接入方法,可以通过maven方式接入,也可以通过gradle方式接入还可以通过Apache Ant方式接入.

  • 依赖接入
    按照官网,我们选择通过gradle接入:

  • 普通转换
    我们定义两个简单的实体进行测试,需要将ComputerDO转换成ComputerDTO

    先定义一个转换接口,再写一个转换方法(支持注解指定)

        @Mapper
        public interface ComputerConverter {
            ComputerConverter INSTANCE = Mappers.getMapper(ComputerConverter.class);
    
            @Mappings({
                    @Mapping(source = "name", target = "computerName")
            })
            ComputerDTO do2Dto(ComputerDO computerDO);
    
            List<ComputerDTO> listDo2Dto(List<ComputerDO> computerDOList);
        }                           
    

    上述两个实体中有一个命名不同的字段,通过@Mapping注解指定对应的转换.
    测试结果:

  • list转换
    实际开发中我们通常还有对应list转换的,MapStruct默认是通过for循环调用单个转换的,所以当我们做list转换时还是需要写单个实体转换,并且把不同的映射字段写好.

  • 特殊转换
    实际开发中通常会出现两个类型不一致的字段进行转换,这种时候一般做法就是单独进行转换后在set值,MapStruct支持这类型的转换

    如上两个类型不一致,我们通过注解指定转换类型

        @Mappings({
                @Mapping(target = "computerName",source = "name"),
                @Mapping(target = "time", dateFormat = "yyyy-MM-dd HH:mm:ss")
        })
        ComputerDTO do2Dto(ComputerDO computerDO);
    

有时候在DO或DTO中有一个list我们期望转换后作为一个String类型,或者是更加特殊的类型,我们应该怎样做?

在转换接口中自定义一个default转换方法 用expression指定这样就可以做到特殊转换.

default方法:Java 8 引入的新的语言特性,用关键字default来标注,被default所标注的方法,需要提供实现,而子类可以选择实现或者不实现该方法

MapStruct 还支持很多特殊的转换技巧,可以通过官网例子进行学习.

MapStruct怎样做到的?

其实我们点开我们所写转换接口的实现类我们就知道这一切的原理.

如上是MapStruct在编译的时候替我们生成的代码,我们一切的注解都通过编译时生成对应的代码,所以在开发的时候可以通过该实现来查看我们所写代码是否有问题.

参考文档

mapstruct官网

mapstruct官网例子

为什么阿里巴巴禁止使用Apache Beanutils进行属性的copy?

丢弃掉那些BeanUtils工具类吧,MapStruct真香!!!

posted @ 2023-02-09 13:57  年年糕  阅读(61)  评论(0编辑  收藏  举报