服务粉丝

我们一直在努力
当前位置:首页 > 财经 >

别再用 BeanUtils 了,这款 PO VO DTO 转换神器不香么?

日期: 来源:石杉的架构笔记收集编辑:bettermann

「 关注“石杉的架构笔记”,大厂架构经验倾囊相授 

文章来源:toutiao.com/i6891531055631696395/



前言


老铁们是不是经常为写一些实体转换的原始代码感到头疼,尤其是实体字段特别多的时候。介绍一个开源项目 mapstruct ,可以轻松优雅的进行转换,简化你的代码。当然有的人喜欢写get set,或者用BeanUtils 进行复制,代码只是工具,本文只是提供一种思路。

先贴下官网地址吧:https://mapstruct.org/

废话不多说,上代码:

pom 配置:

<properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <org.mapstruct.version>1.4.1.Final</org.mapstruct.version>
        <org.projectlombok.version>1.18.12</org.projectlombok.version>
</properties>

<dependencies>
        <dependency>
            <groupId>org.mapstruct</groupId>
            <artifactId>mapstruct</artifactId>
            <version>${org.mapstruct.version}</version>
        </dependency>

        <!-- lombok dependencies should not end up on classpath -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>${org.projectlombok.version}</version>
            <scope>provided</scope>
        </dependency>

        <!-- idea 2018.1.1 之前的版本需要添加下面的配置,后期的版本就不需要了,可以注释掉,
我自己用的2019.3 -->
     <dependency>
            <groupId>org.mapstruct</groupId>
            <artifactId>mapstruct-processor</artifactId>
            <version>${org.mapstruct.version}</version>
            <scope>provided</scope>
        </dependency>

</dependencies>

<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.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                            <version>${org.projectlombok.version}</version>
                        </path>
                        <path>
                            <groupId>org.mapstruct</groupId>
                            <artifactId>mapstruct-processor</artifactId>
                            <version>${org.mapstruct.version}</version>
                        </path>
                    </annotationProcessorPaths>
                </configuration>
            </plugin>
        </plugins>
    </build>

关于lombok和mapstruct的版本兼容问题多说几句,maven插件要使用3.6.0版本以上、lombok使用1.16.16版本以上,另外编译的lombok mapstruct的插件不要忘了加上。否则会出现下面的错误:No property named "aaa" exists in source parameter(s). Did you mean "null"?

这种异常就是lombok编译异常导致缺少get setter方法造成的。还有就是缺少构造函数也会抛异常。

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class Student {

    private String name;
    private int age;
    private GenderEnum gender;
    private Double height;
    private Date birthday;

}
public enum GenderEnum {
    Male("1", "男"),
    Female("0", "女");

    private String code;
    private String name;

    public String getCode() {
        return this.code;
    }

    public String getName() {
        return this.name;
    }

    GenderEnum(String code, String name) {
        this.code = code;
        this.name = name;
    }
}
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class StudentVO {
    private String name;
    private int age;
    private String gender;
    private Double height;
    private String birthday;
}
@Mapper
public interface StudentMapper {

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

    @Mapping(source = "gender.name", target = "gender")
    @Mapping(source = "birthday", target = "birthday", dateFormat = "yyyy-MM-dd HH:mm:ss")
    StudentVO student2StudentVO(Student student);

}

实体类是开发过程少不了的,就算是用工具生成肯定也是要有的,需要手写的部分就是这个Mapper的接口,编译完成后会自动生成相应的实现类

然后就可以直接用mapper进行实体的转换了

public class Test {

    public static void main(String[] args) {

        Student student = Student.builder().name("小明").age(6).gender(GenderEnum.Male).height(121.1).birthday(new Date()).build();
        System.out.println(student);
        //这行代码便是实际要用的代码
        StudentVO studentVO = StudentMapper.INSTANCE.student2StudentVO(student);
        System.out.println(studentVO);

    }

}

mapper可以进行字段映射,改变字段类型,指定格式化的方式,包括一些日期的默认处理。

可以手动指定格式化的方法:

@Mapper
public interface StudentMapper {

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

    @Mapping(source = "gender", target = "gender")
    @Mapping(source = "birthday", target = "birthday", dateFormat = "yyyy-MM-dd HH:mm:ss")
    StudentVO student2StudentVO(Student student);

    default String getGenderName(GenderEnum gender) {
        return gender.getName();
    }

}

上面只是最简单的实体映射处理,下面介绍一些高级用法



1.List 转换


属性映射基于上面的mapping配置

@Mapper
public interface StudentMapper {

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

    @Mapping(source = "gender.name", target = "gender")
    @Mapping(source = "birthday", target = "birthday", dateFormat = "yyyy-MM-dd HH:mm:ss")
    StudentVO student2StudentVO(Student student);


    List<StudentVO> students2StudentVOs(List<Student> studentList);

}
public static void main(String[] args) {

    Student student = Student.builder().name("小明").age(6).gender(GenderEnum.Male).height(121.1).birthday(new Date()).build();

    List<Student> list = new ArrayList<>();
    list.add(student);
    List<StudentVO> result = StudentMapper.INSTANCE.students2StudentVOs(list);
    System.out.println(result);
}




2.多对象转换到一个对象



@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class Student {

    private String name;
    private int age;
    private GenderEnum gender;
    private Double height;
    private Date birthday;

}
@Data
@AllArgsConstructor
@Builder
@NoArgsConstructor
public class Course {

    private String courseName;
    private int sortNo;
    private long id;

}
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class StudentVO {
    private String name;
    private int age;
    private String gender;
    private Double height;
    private String birthday;
    private String course;
}
@Mapper
public interface StudentMapper {

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

    @Mapping(source = "student.gender.name", target = "gender")
    @Mapping(source = "student.birthday", target = "birthday", dateFormat = "yyyy-MM-dd HH:mm:ss")
    @Mapping(source = "course.courseName", target = "course")
    StudentVO studentAndCourse2StudentVO(Student student, Course course);

}
public class Test {

    public static void main(String[] args) {

        Student student = Student.builder().name("小明").age(6).gender(GenderEnum.Male).height(121.1).birthday(new Date()).build();
        Course course = Course.builder().id(1L).courseName("语文").build();

        StudentVO studentVO = StudentMapper.INSTANCE.studentAndCourse2StudentVO(student, course);
        System.out.println(studentVO);
    }

}



3、默认值


@Mapper
public interface StudentMapper {

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

    @Mapping(source = "student.gender.name", target = "gender")
    @Mapping(source = "student.birthday", target = "birthday", dateFormat = "yyyy-MM-dd HH:mm:ss")
    @Mapping(source = "course.courseName", target = "course")
    @Mapping(target = "name", source = "student.name", defaultValue = "张三")
    StudentVO studentAndCourse2StudentVO(Student student, Course course);

}


欢迎扫码加入儒猿技术交流群,每天晚上20:00都有Java面试、Redis、MySQL、RocketMQ、SpringCloudAlibaba、Java架构等技术答疑分享,更能跟小伙伴们一起交流技术


另外推荐儒猿课堂的9.9元系列课程给您,欢迎加入一起学习~


互联网Java工程师面试突击课
(9.9元专享)

SpringCloudAlibaba零基础入门到项目实战
9.9元专享)

亿级流量下的电商详情页系统实战项目
9.9元专享)

Kafka消息中间件内核源码精讲
9.9元专享)

12个实战案例带你玩转Java并发编程
9.9元专享)

Elasticsearch零基础入门到精通
9.9元专享)

基于Java手写分布式中间件系统实战
9.9元专享)

基于ShardingSphere的分库分表实战课
9.9元专享)

相关阅读

  • RocketMQ从入门到放弃~~~

  • 原价199元,现在参加拼团活动立享优惠价仅 99 元,赶快一起参团吧!《基于电商营销场景的高并发RocketMQ实战》=== 课程福利 ===为了让更多同学学到赚到,《基于电商营销场景的高并
  • JVM常用排查工具这些你都会用吗

  • 关注我,回复关键字“spring”,免费领取Spring学习资料。阅读本文你可以学到以下命令的常规使用【jps,jinfo,jstat,jmap,jstack,jcmd,jrunscript,jjs】jps获取当前运行中java进程,示例:j
  • 迈向卓越 - 闲鱼终端场景CI能力体系化建设

  • 闲鱼从2014年创立,到2022年已经走过了8个年头,闲鱼APP也随之逐渐复杂。在这其中,我们也面临着大型APP共性的一些通病,例如:团队规模变大带来的研发效能瓶颈的问题,大量历史代码带
  • 实战 | 记一次xxe漏洞的奇怪绕过

  • 又是平平无奇的一天开局就是目录扫描Api.html存活发现接口泄露接口未授权获取管理员账号密码,发现用的xml格式加载,有可能存在xxe漏洞还是个弱口令登录后台看看本次目标明确直
  • C盘漂红爆满怎么办?手把手教你搞定!

  • “设为星标”第一时间接收推送,精彩内容不容错过!前言通常情况下,我们电脑的第一个盘符都是C盘,在你未修改盘符的情况下,C盘也是Windows系统的系统盘。随着使用时间的增加,C盘就会

热门文章

  • “复活”半年后 京东拍拍二手杀入公益事业

  • 京东拍拍二手“复活”半年后,杀入公益事业,试图让企业捐的赠品、家庭闲置品变成实实在在的“爱心”。 把“闲置品”变爱心 6月12日,“益心一益·守护梦想每一步”2018年四

最新文章

  • 三月指数基金配置建议

  • 1二月份市场的震荡主要有两个原因:一个是经济活动恢复时,资金从金融市场流向实体经济,央行因为去年已经投放了太多的流动性,为防止大水漫灌,只是采用了托底流动性投放,导致股市的
  • 你的基金总是“过山车”怎么办?

  • 公众号规则是部分推送,您只有设了星标⭐️,才能及时接收最新推送每周二原创:职场学习类干货走出“避免后悔”的心理误区1/6纸上富贵一场基民聊天,最常见的话题之一就是“曾经涨到
  • 最近,北京一处传统、古老的旅游目的地——鼓楼,成网红打卡地,客流量猛增。7日,总台融媒体节目《两会你我他》中,央视新闻《相对论》记者庄胜春来到北京鼓楼,一探究竟↓鼓楼变网红
  • 她们,真的“剧”“美”“力”!

  • 女性生来具备力量不被定义,无关年龄她们追梦的身影处处可见在总台播出的影视剧中许多职场女性角色令人印象深刻她们来自不同的领域处于不同的阶段经历着不同的人生或普通 或
  • RocketMQ从入门到放弃~~~

  • 原价199元,现在参加拼团活动立享优惠价仅 99 元,赶快一起参团吧!《基于电商营销场景的高并发RocketMQ实战》=== 课程福利 ===为了让更多同学学到赚到,《基于电商营销场景的高并