对象之间的拷贝与转换

news2024/11/17 16:42:16

这里写目录标题

  • 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);

调用接口就可以使用了

	UserConverter INSTANCE = Mappers.getMapper(UserConverter.class);
    UserVo userVo = UserConverter.INSTANCE.do2vo(user);
	User user = UserConverter.INSTANCE.vo2Do(userVo);

当添加 componentModel=“spring” 时,它会在实现类上自动添加 @Component 注解,这样就能被 Spring 记住 component scan,从而加载到 springContext 中,进而被 @Autowird 注入使用

@Mapper(componentModel="spring")
public interface UserConverter {
}

@SpringBootTest
public class UserConverterTest {
  
  @Resource
  private UserConverter userConverter;
  
}

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

简单说一下该库的原理。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 配置文件、注解、API 的方式配置映射规则

<dependency>
    <groupId>net.sf.dozer</groupId>
    <artifactId>dozer</artifactId>
    <version>5.4.0</version>
</dependency>

关于该库的最简单的使用,是直接用 API

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

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

相关文章

【Qt】11.Linux下,Qt程序打包

目录 获取Release模式下的可执行文件 打包的目录结构搭建 安装linuxdeployqt 环境准备 下载linuxdeployqt 编译安装 复制快捷方式 配置环境变量 使生效 查看版本 安装unixODBC库 解压 配置 编译安装 重启系统 打包 原因 解决方法 打成deb包 打deb包目录构建…

Python虚拟环境大总结(virtualenv pipenv)

文章目录1 virtualenv1.1 安装1.2 测试安装是否成功1.3 主要命令1.4 virtualenvwrapper1.4.1 创建虚拟环境1.4.2 列举所有虚拟环境1.4.3 激活虚拟环境1.4.4 取消激活虚拟环境1.4.5 删除虚拟环境1.4.6 创建指定版本的虚拟环境2 pipenv2.1 安装2.2 创建虚拟环境2.3 进入虚拟环境2…

游戏之外,元宇宙也在寻求与更多领域进行融合

在大众对元宇宙的构想中&#xff0c;“游戏”是优先级最高的落地场景之一。《头号玩家》、《赛博朋克2077》等作品中&#xff0c;“游戏”也多次成为元宇宙的主要载体&#xff0c;描画出人们对于这一前沿风口的想象。 2022年以来&#xff0c;监管侧陆续传来元宇宙产业发展的利…

python算法加密 pyarmor与docker

如觉得博主文章写的不错或对你有所帮助的话&#xff0c;还望大家多多支持呀&#xff01;关注、点赞、收藏、评论。 目录一、 基本语法 加密 Python 脚本二、运行加密脚本三、pyarmor&docker3.1 Dockerfile3.2 requirements.txt3.3 加密函数lock_by_pyarmor.py3.4 主函数myp…

元宵节营销活动策划,轻松拿下用户

热闹的春节刚过&#xff0c;又将迎来团圆美满的元宵节&#x1f3ee;。我们今天就来讲讲&#xff0c;关于节日营销的小巧思&#xff01; 【产品游戏】 在每一个关于节日的营销里&#xff0c;将游戏作为切入点与产品相结合&#xff0c;往往可以获得意想不到的效果。对于场景单一…

DynaSLAM-6 DynaSLAM论文解读

目录 1.论文摘要解读 1.1 原论文内容 1.2 个人理解 2.论文discusses related work部分 2.1 原论文内容 3.论文SYSTEM DESCRIPTION部分 3.1 使用Mask R-CNN对潜在的动态内容进行分割 3.2 低成本追踪 3.3 使用Mask R-CNN和多视角几何对动态内容进行分割 3.4 跟踪线程…

分享会上狂吹MySQL的4大索引结构红黑树、二叉树B+Tree,没想到~~~~

索引&#xff08;index&#xff09;是帮助MySQL高效获取数据的数据结构(有序)。在数据之外&#xff0c;数据库系统还维护着满足 特定查找算法的数据结构&#xff0c;这些数据结构以某种方式引用&#xff08;指向&#xff09;数据&#xff0c; 这样就可以在这些数据结构 上实现高…

品优购网页制作

目录 favicon图标 TDK三大标签SEO优化 title网站标题 description网站说明 keywords关键字 首页制作 快捷导航模块 左浮动 右浮动 header头部模块制作 1.logo模块 2.search模块 3.热词模块 4.购物车模块 子绝父绝 nav导航模块 1.nav左边导航位置 2.上方导航位置 …

PCB覆铜很“上头”?一文帮你搞定实操要点和规范

1、覆铜覆盖焊盘时&#xff0c;要完全覆盖&#xff0c;shape 和焊盘不能形成锐角的夹角。2、尽量用覆铜替代粗线。当使用粗线时&#xff0c;过孔通常为非通常走线过孔&#xff0c;增大过孔的孔径和焊盘。修改后&#xff1a;3、尽量用覆铜替换覆铜走线的模式&#xff0c;后者常常…

11.深度优先搜索

一、算法内容 1.简介 深度优先搜索DFS&#xff08;Depth First Search&#xff09;按照深度优先的方式进行搜索&#xff0c;可以理解为“一条路走到黑”地穷举所有可行的方案&#xff0c;并不断尝试&#xff0c;直到找到一种情况满足问题问题的要求。那么这个方案就是一个问题…

shell 循环学习练习

目录 一&#xff0c;嵌套循环实现9*9乘法表 二&#xff0c;判定一个成绩&#xff1a; 三&#xff0c;循环创建用户&#xff1a;用户名为user01-user20 一&#xff0c;嵌套循环实现9*9乘法表 (for和while都可以) 选做&#xff1a;格式对齐&#xff0c;以及使用单层循环完成9*9乘…

精细管理——CRM销售漏斗管理

CRM销售漏斗涵盖了从接触客户到谈判、成单、回款的整个销售过程。一个典型的销售漏斗是由一个特定时间段里&#xff0c;例如一年或者一个季度或者一个月这个时间范畴之内&#xff0c;一系列有可能转化成订单的潜在销售机会所组成。在CRM客户管理系统中&#xff0c;销售漏斗管理…

Unity-TCP-网络聊天功能(四): 消息粘包、心跳机制保活(心跳包)、断线重连

8. 粘包Bug、心跳机制保活(心跳包)、断线重连粘包bug1&#xff1a;下线后&#xff0c;如果发送多条消息&#xff0c;在客户端上线时&#xff0c;一瞬间接收到&#xff0c;效果如同粘包&#xff0c;需要拆包。举例&#xff0c;连续发送三条160长度消息&#xff0c;可能实际显示2…

java常用类: System类直接常用方法

java常用类型: Ineteger等包装类 String类&#xff0c;StringBuffer类和StringBuilder类 Math类及常用方法 System类及常用方法 Arrays类及常用方法 BigInteger类和BigDecimal类及常用方法 日期类Date类,Calender类和LocalDateTime类 文章目录System简介System.exit(0) 退出Sys…

蓝桥杯重点(C/C++)(随时更新,更新时间:2023.2.2)

点关注不迷路&#xff0c;欢迎推荐给更多人&#xff0c;大约两天更新一次&#xff0c;建议点赞收藏加关注 本次更新内容&#xff1a;1.STL部分详细讲述&#xff0c;放到一篇新的文章中 2. 部分细节优化 目录 1 技巧 1.1 取消同步&#xff08;节约时间&#xff0c;甚至能多…

Shield UI for JavaScript 1.7.44 Crack

Shield UI for JavaScript Shield UI JavaScript 框架提供具有响应式设计的 JavaScript HTML5 组件&#xff0c;这些组件经过优化以获得最佳性能。 Shield UI 在 70 多种小部件类型中提供了最快和高度可定制的网格和图表控件。每个单独的控件都由行业领先的 24/7 支持包提供支持…

以莫罗湾为例,利用高精度地形高程模型应对海岸环境变化

Morro Bay是位于加州 San Luis Obispo附近的浅海河口区&#xff0c;存在大量野生动物&#xff0c;也是人们户外活动的好去处。但是沉积变化和鳗草&#xff08;大叶藻&#xff09;的大量消失对河口景观产生了不利影响。为了更好地认识环境改变的路径并提取修复对策&#xff0c;M…

2023年山东最新建筑八大员(资料员)考试试题题库及答案

百分百题库提供建筑八大员&#xff08;资料员&#xff09;考试试题、建筑八大员&#xff08;资料员&#xff09;考试预测题、建筑八大员&#xff08;资料员&#xff09;考试真题、建筑八大员&#xff08;资料员&#xff09;证考试题库等,提供在线做题刷题&#xff0c;在线模拟考…

Vue实战第3章:主页设计之顶部导航栏

主页设计之顶部导航栏 前言 本篇在讲什么 本篇文章主要来制作一个导航栏&#xff0c;具体效果就按照下图来处理吧 本篇适合什么 适合初学Vue的小白 想了解建站的同学 本篇需要什么 对Html语法有简单认知 对CSS语法有简单认知 对Vue有简单认知 依赖VS Code编辑器 本…

【redis6】第十三章(主从复制)

是什么 主机数据更新后根据配置和策略&#xff0c; 自动同步到备机的master/slaver机制&#xff0c;Master以写为主&#xff0c;Slave以读为主 能干嘛 读写分离&#xff0c;性能扩展 容灾快速恢复 怎么玩 拷贝多个redis.conf文件include(写绝对路径) 开启daemonize yes Pi…