对象之间的拷贝

news2024/12/26 11:24:54

这里写目录标题

  • Lambda 的 builder
  • idea 自动生成插件 GenerateAllSetter
  • MapStruct
  • Dozer

在开发的时候经常会有业务代码之间有很多的 JavaBean 之间的相互转化,比如 PO/DTO/VO/QueryParam 之间的转换问题,本文总结一下各种转换方法

Lambda 的 builder

使用构造器模式快速的生成一个 pojo 对象

@Data
@Builder
public class UserVo {
    private Long id;
    private String username;
    private String password; // 密码
    private Integer sex;  // 性别
    private LocalDate birthday; // 生日
    private LocalDateTime createTime; // 创建时间
    private String config; // 其他扩展信息,以JSON格式存储
    public UserVo toUserVo(User user) {
        return User user = new User()
            .setId(1L)
            .setUsername("zhangsan")
            .setSex(1)
            .setPassword("abc123")
            .setCreateTime(LocalDateTime.now())
            .setBirthday(LocalDate.of(1999, 9, 27))
            .setConfig("[{\"field1\":\"Test Field1\",\"field2\":500}]");
    }
}

idea 自动生成插件 GenerateAllSetter

idea 有款叫 GenerateAllSetter 的插件,使用方法:Alt + Enter,在转换方法中自动生成转换代码

    private OperationNonComplianceVo toOperationNonComplianceVo() {
        OperationNonComplianceVo operationNonComplianceVo = OperationNonComplianceVo.builder()
        		.date()
        		.shopName()
        		.customerName()
        		.orderNo()
        		.orderTime()
        		.destinationName()
        		.grabTime()
        		.defectType()
        		.reassignmentTime()
        		.departurePlace()
        		.contacts()
        		.orderNum()
        		.build();
        return operationNonComplianceVo;
	}

MapStruct

MapSturct 是一个生成类型安全, 高性能且无依赖的 JavaBean 映射代码的注解处理器(annotation processor)。工具可以帮我们实现 JavaBean 之间的转换, 通过注解的方式。同时, 作为一个工具类,相比于手写, 其具有便捷, 不容易出错的特点

MapStruct 的使用首先需要引入依赖

    <dependency>
        <groupId>org.mapstruct</groupId>
        <artifactId>mapstruct</artifactId>
    </dependency>

由于 MapStruct 在编译时工作,其代码生成原理类似 Lambda。会集成到像 Maven 和 Gradle 这样的构建工具上,我们还必须在<build中/>标签中添加一个插件 maven-compiler-plugin,并在其配置中添加 annotationProcessorPaths

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.5.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>
                </annotationProcessorPaths>
            </configuration>
        </plugin>
    </plugins>
</build>

做好了前置工作之后就可以使用了,pojo 如下:

	@Data
	@Accessors(chain = true)
	public class User {
	    private Long id;
	    private String username;
	    private String password; // 密码
	    private Integer sex;  // 性别
	    private LocalDate birthday; // 生日
	    private LocalDateTime createTime; // 创建时间
	    private String config; // 其他扩展信息,以JSON格式存储
	}
	@Data
	@Accessors(chain = true)
	public class UserVo {
	    private Long id;
	    private String username;
	    private String password;
	    private Integer gender;
	    private LocalDate birthday;
	    private String createTime;
	    private List<UserConfig> config;
	    @Data
	    public static class UserConfig {
	        private String field1;
	        private Integer field2;
	    }
	}

@mapper 注解可以直接作用与接口上,实现模型之间的转换,默认让对象中相同名称的属性相互转换,入参为需要转换的对象,返回值为被转换的对象,同时,list也可以进行转换

@Mapper
public interface UserConverter {
    UserConverter INSTANCE = Mappers.getMapper(UserConverter.class);

	// 如果有不相同名称的属性需要转换,可以加上 @Mapping 注解
    @Mapping(target = "gender", source = "sex")
    // 如果有时间类需要转换为字符串或者字符串需要转换为时间类,可以这么写
    @Mapping(target = "createTime", dateFormat = "yyyy-MM-dd HH:mm:ss")
    UserVo do2vo(User var1);

    @Mapping(target = "sex", source = "gender")
    // 转换的时候忽略密码
    @Mapping(target = "password", ignore = true)
    @Mapping(target = "createTime", dateFormat = "yyyy-MM-dd HH:mm:ss")
    User vo2Do(UserVo var1);

    List<UserVo> do2voList(List<User> userList);

    default List<UserVo.UserConfig> strConfigToListUserConfig(String config) {
        return JSON.parseArray(config, UserVo.UserConfig.class);
    }

    default String listUserConfigToStrConfig(List<UserVo.UserConfig> list) {
        return JSON.toJSONString(list);
    }
}

其对应的信息不仅仅来自一个类, 那么, 我们也可以通过配置来实现多到一的转换

	@Mapping(target = "periodId", source = "studentDetailsPo.periodId")
	@Mapping(target = "studentName", source = "userPo.name")
	StudentInfoVo convert(UserPo userPo, StudentDetailsPo studentDetailsPo);

转换器的位置应该放在这里
在这里插入图片描述

简单说一下该库的原理。MapStruct 来生成的代码,其类似于人手写 get 与 set,并且是在编译时生成,比运行时生成数据要快不少

其过程为 JVM 编译时解析该库中的注解(还有一种注解解析方式为运行时解析),本质上就是一个实现了 JSR 269 API 的程序。在使用 javac 的过程中,它产生作用的具体流程如下:

  • javac 对源代码进行分析,生成了一棵抽象语法树(AST)
  • 运行过程中调用实现了 JSR 269 API 的 MapStruct 程序
  • 此时就对第一步骤得到的 AST 进行处理,找到 @Data 注解所在类对应的语法树(AST),然后修改该语法树(AST),增加 getter 和 setter 方法定义的相应树节点
  • javac 使用修改后的抽象语法树(AST)生成字节码文件,即给 class 增加新的节点(代码块)

Dozer

Dozer 是 Java Bean 到 Java Bean 映射器,它以递归方式将数据从一个对象复制到另一个对象。支持简单属性映射,复杂类型映射,双向映射,隐式显式映射以及递归映射。另外,Dozer不仅支持属性名称之间的映射,还支持在类型之间自动转换。大多数转换方案都是开箱即用的,如果无法完成映射(比如使用属性名映射的时候,名称不同),还允许通过xml配置文件的形势配置映射规则

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

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

相关文章

有幸得到Alibaba内部Gradle实战笔记,趁机狂补

虽然一直在接触 Gradle&#xff0c;但对 Gradle 始终都有一些陌生感&#xff0c;表现在日常的开发中就是不敢随便改 build.gradle 文件&#xff0c;一旦 sync 出错&#xff0c;只会复制错误找谷歌&#xff0c;可是解决方案也不一定能够完美解决自己的问题。还有就是不熟悉 Grad…

黑客为什么都有一台笔记本电脑?

用一位程序员的话俩说&#xff1a;虽然我不是黑客&#xff0c;但是我也喜欢弄一些编程&#xff0c;对我而言&#xff0c;电脑就是我的工具&#xff0c;我的系统里面肯定有许多我自己写的程序&#xff0c;在我做任何操作的时候&#xff0c;我肯定使用我熟悉的软件&#xff0c;这…

创建者模式—工厂模式

目录 1.工厂模式 1.1概述 1.2简单工厂模式 1.2.1结构 1.2.2实现 1.2.3优缺点 1.2.4静态工厂 1.3工厂方法模式 1.3.1概念 1.3.2结构 1.3.3实现 1.3.4优缺点 1.4抽象工厂模式 1.4.1概念 1.4.2结构 1.4.3实现 1.4.4优缺点 1.工厂模式 1.1概述 需求&#xff1a;设…

易基因|细菌全基因组甲基化纳米孔测序(ONT):技术推介

大家好&#xff0c;这是专注表观组学十余年&#xff0c;领跑多组学科研服务的易基因。今天跟大家介绍一下易基因的新产品&#xff1a;细菌全基因组甲基化纳米孔测序&#xff08;ONT&#xff09;。表观修饰不需要改变DNA序列便能实现对性状的改变&#xff0c;表观修饰的改变与基…

什么是事务?什么是索引?什么是视图?

目录 一、事务 二、视图 1 、视图概念 2、为什么要使用视图 3 、性能问题 4 、定义视图 5、查看视图 6、删除视图 三、索引 1、引入索引的问题 2、索引是什么 3、索引为什么选择b树 一、事务 事务是什么&#xff1f; 事务是一个操作序列&#xff0c;这些操作要么都…

Python+Selenium+Unittest 之selenium2--元素定位1-简介

这篇先说下webdriver的几种元素定位方式&#xff0c;让大家有个大概的了解&#xff0c;UI自动化说白了就是使用代码代替人工去进行操作&#xff0c;在页面上&#xff0c;执行人员可以直接对看到的任何地方进行点击、拖动等操作&#xff0c;而代码的话需要识别到到底要点那个按钮…

生产制造业ERP管理系统对于制造企业的好处有哪些?

任何一家企业在管理当中都存在或多或少的问题&#xff0c;这些问题对企业的发展都形成了一定的阻碍。在生产制造业当中&#xff0c;由于每日的繁重的生产计划和大量的生产作业&#xff0c;使得企业管理存在一些问题&#xff0c;这些问题不利于生产的有序进行&#xff0c;从而阻…

图表控件LightningChart.NET 系列教程(八):用代码创建图表

LightningChart.NET SDK 是一款高性能数据可视化插件工具&#xff0c;由数据可视化软件组件和工具类组成&#xff0c;可支持基于 Windows 的用户界面框架&#xff08;Windows Presentation Foundation&#xff09;、Windows 通用应用平台&#xff08;Universal Windows Platfor…

【微服务】分布式事务Seata

分布式事务Seata1.分布式事务问题1.1.本地事务1.2.分布式事务2.理论基础2.1.CAP定理2.1.1.一致性2.1.2.可用性2.1.3.分区容错2.1.4.矛盾2.2.BASE理论2.3.解决分布式事务的思路3.初识Seata3.1.Seata的架构3.2.部署TC服务3.3.微服务集成Seata3.3.1.引入依赖3.3.2.配置TC地址3.3.3…

商用清洁机器人:科沃斯“破圈”、高仙机器人“纵深”

配图来自Canva可画 正所谓科技改变生活&#xff0c;机器人在人们日常生活中出现的频率正在逐步提高。同时&#xff0c;随着智能技术的不断迭代升级、用户需求的增多&#xff0c;机器人的应用场景逐步拓宽、功能形态也愈发多样化&#xff0c;比如配送机器人、医疗机器人、教育机…

Android 12.0 启动app时设置密码锁

1.前言 1.1概述 在12.0的系统产品开发中,对于限制某些app的启动的功能中,在项目中的需求是在点击app启动的时候,根据包名设置密码锁,当输入正确的密码的时候来启动这个app,否则 就不能启动这个app,达到限制使用app的目的,这就需要在app启动的时候,检测app的包名,然后在…

分布式架构的必问理论

基础理论&#xff1a; CAP理论&#xff1a; CAP理论是分布式系统设计中最基础、也是最为关键的理论&#xff0c;它指出&#xff0c;分布式数据存储不可能同时满足以下三个条件。 一致性&#xff08;Consistency&#xff09;&#xff1a;每次读取要么获得最近写入的数据&…

OAuth2 (二)

目录 创建项目结构 父工程 客户 认证服务器 资源拥有者 资源服务器 创建项目结构 演示代码下载&#xff1a; https://gitee.com/lisenaq/oauth2-example.git 演示客户发请求&#xff1a; http://localhost:8080/client/getCode 父工程 父工程有:子模块需要重新导入该…

CVE-2022-34916 Apache Flume 远程代码执行漏洞分析

项目介绍 Apache Flume 是一个分布式的&#xff0c;可靠的&#xff0c;并且可用于高效地收集&#xff0c;汇总和移动大量日志数据的软件。它具有基于流数据流的简单而灵活的体系结构。它具有可调的可靠性机制以及许多故障转移和恢复机制&#xff0c;并且具有健壮性和容错性。它…

Spring/SpringBoot/SpringCloud面试题

SpringBoot和SpringMVC的区别 形式上&#xff1a;SpringBoot是一个自动化配置的工具&#xff1b;SpringMVC是一个web框架在搭建项目时&#xff1a;SpringMVC需要手动配置xml文件&#xff0c;同时需要配置Tomcat服务器。而SpringBoot采用约定大于配置的方式&#xff0c;进行自动…

【Linux系统】第五篇:Linux中编译器gcc/g++的使用

文章目录一、编译工具gcc/g二、程序编译的过程&#x1f384;预处理&#x1f384;编译&#x1f384;汇编&#x1f384;链接三、动态链接和静态链接&#x1f33b;动态链接&#x1f33b;静态链接&#x1f33b; 程序动、静态链接的区分一、编译工具gcc/g gcc/g 分别是 C/C 的编译器…

【wp】hgame2023 week3 RePwn

【wp】hgame2023 week3 Re&&Pwn Re cpp那个chacha20加密不会。 kunmusic 用dnspy逆dll&#xff0c;在Program的Main方法中找到了初始化的数据 下断点执行&#xff0c;拷贝出data 写一份脚本进行data与104的异或 def step_one():with open("./data", enc…

发明专利申请流程资料

​发明专利申请流程 依据专利法&#xff0c;发明专利申请的审批程序分为&#xff1a; 1、受理阶段 2、初步审查阶段 3、公布阶段 4、实质审查阶段 5、授权阶段 发明专利申请所需资料 1、发明专利请求书。 2、说明书。 3、权利要求书。 4、说明书摘要。 5、有附图的可同时提交说…

Actionchains在selenium中的使用方法

今天分享一下selenium最常用的ActionChains的使用&#xff0c;以及碰到的一些问题的解决。 1.selenium解决鼠标悬停的问题 今天抓取某个平台的数据时发现有的数据需要鼠标悬停在上面才能加载出来&#xff0c;于是就想到了使用ActionChains解决悬停的问题&#xff0c;下面是思…

计算机组成原理 | 第九章:控制单元的功能 | 微操作命令 | 时钟周期

文章目录&#x1f4da;微操作命令的分析&#x1f407;取指周期&#x1f407;间址周期&#x1f407;执行周期&#x1f955;非访存指令&#x1f955;访存指令⭐️&#x1f955;转移指令&#x1f407;中断周期&#x1f4da;控制单元的功能&#x1f407;控制单元的外特性&#x1f9…