DTO转VO工具

news/2024/11/15 11:24:38/文章来源:https://www.cnblogs.com/qimoxuan/p/18308566

data工具,实现了对象拷贝 DTO -> VO 只需要实现一个类即可

data-utils

data工具,实现了对象拷贝DTO —> VO

解决的问题

Mapstruct需要安插件!!!!很多云桌面等会很不方便
org.springframework.beans.BeanUtils有一个 copyProperties的方法

@Data
@AllArgsConstructor
@NoArgsConstructor
public class AccountDTO  {private Long id;private String username;private String password;private String gender;private String email;private String role;private Date registerTime;private Integer isDelete;
}
@Data
public class AccountVO {private String username;private String gender;private String role;//男 1 女 0private String genderNum;private Integer isDelete;
}

比如我们有两个类 DTO 和 VO 在给前端VO的时候,需要把DTO 转换成VO 我们需要这样写 遇到genderNumDTO类里没有的这种情况,我们需要手动set的时候,是下面这种写法

import com.example.entity.AccountVO;@Data
public class DataTest {@Testvoid contextLoads1() {AccountDTO accountDTO = new AccountDTO(1L, "test", "123456", "男", "112@qq.com", "user", new Date(), 1);AccountVO accountVO =  new AccountVO();BeanUtils.copyProperties(accountDTO, accountVO);accountVO.setGender(Objects.equals(accountDTO.getGender(), "男") ? "1" : "0");System.out.println(accountVO);}
}

有两个缺点:
1.VO需要手动new一个出来
2.如果VO里面有很多字段需要手动set的时候,会把代码写的很长
3.如果遇到集合里面想要转换, sonar还会报不让在循环中创建对象的问题

BaseData的作用

BaseData代码(项目里只要有这个就可以)

import com.example.common.Constants;
import com.example.common.ErrorCode;
import com.example.exception.BusinessException;
import org.springframework.util.ReflectionUtils;import java.lang.reflect.*;
import java.util.Arrays;
import java.util.function.Consumer;public interface BaseData {/*** 默认方法,根据传入的Class3类型将当前对象转换为目标对象并执行操作** @param clazz    目标类* @param consumer 可以写lambda表达式比如*  accountDTO.asTargetObject(AccountVO.class,v->{*      v.setGenderNum(Objects.equals(accountDT0.getGender(),"男")?"1":"0");*          });*  consumer是这段*  v->{*      v.setGenderNum(Objects.equals(accountDT0.getGender(),"男")?"1":"0");*  }*/default <V> V asTargetObject(Class<V> clazz, Consumer<V> consumer) {//        调用 asTargetObject 方法将当前对象转换为目标对象V v = this.asTargetObject(clazz);//        执行传入的Consumer操作
        consumer.accept(v);return v;}/*** 默认方法 将当前对象转换为目标对象** @param clazz 目标类* @param <V>   目标类类型 如AccountVO* @return 转换完的目标类*/default <V> V asTargetObject(Class<V> clazz) {try {//            获取目标类的所有字段Field[] declaredFields = clazz.getDeclaredFields();//            获取目标类的构造函数Constructor<V> constructor = clazz.getConstructor();//            根据构造函数实例化目标对象V v = constructor.newInstance();//            遍历目标类的每个字段,并进行转换试值Arrays.stream(declaredFields).forEach(declaredField -> convert(declaredField, v));return v;} catch (ReflectiveOperationException e) {//            //捕获ReflectiveOperationException异常,抛出自定义的BusinessExceptionthrow new BusinessException(ErrorCode.CAST_OBJECT_ERROR);}}/*** 默认方法,将字段转换并赋值给目标对象* @param field VO剩余的字段,自定义* @param vo    要转换的VO*/default void convert(Field field, Object vo) {try {//            获取当前对象中与目标字段同名的字段Field source = this.getClass().getDeclaredField(field.getName());//            设置字段可访问
            ReflectionUtils.makeAccessible(field);ReflectionUtils.makeAccessible(source);//            获取当前对象中获取字段值的方法和目标对象中设置字段值的方法,并进行转换赋值Method sourceGetter = this.getClass().getMethod(Constants.GET + capitalize(field.getName()));Method targetSetter = vo.getClass().getMethod(Constants.SET + capitalize(field.getName()), field.getType());Object value = sourceGetter.invoke(this);targetSetter.invoke(vo, value);} catch (NoSuchFieldException | InvocationTargetException | IllegalAccessException |NoSuchMethodException ignored) {//              这里ignored 原因是//              两个类的字段数量不一样的时候,会报 java.lang.NoSuchFieldException//              但是多出来的字段我们是可以处理的
        }}/*** 默认方法,将字符串首字母大写* @param str   比如字段名 name* @return 返回 Name*/default String capitalize(String str) {if (str == null || str.isEmpty()) {return str;}return Character.toUpperCase(str.charAt(0)) + str.substring(1);}
}

1.实现对象深拷贝

@Data
public class DataTest {@Testvoid contextLoads1() {AccountDTO accountDTO = new AccountDTO(1L,"test","123456","男","112@qq.com","user",new Date(),1);AccountVO accountVO = accountDTO.asTargetObject(AccountVO.class,v->{v.setGenderNum(Objects.equals(accountDTO.getGender(), "男") ? "1" : "0");});System.out.println(accountVO);}
}

1.实现对象Collection深拷贝(List Set...)

@Data
public class DataTest {@Testvoid contextLoads2() {AccountDTO accountDTO = new AccountDTO(1L,"test","123456","男","112@qq.com","user",new Date(),0);AccountDTO accountDTO2 = new AccountDTO(2L,"test2","123456","女","112@qq.com","admin",new Date(),1);List<AccountDTO> accountDTOList = new ArrayList<>();accountDTOList.add(accountDTO);accountDTOList.add(accountDTO2);List<AccountVO> list = accountDTOList.stream().map(source -> source.asTargetObject(AccountVO.class, v-> {v.setGenderNum(Objects.equals(source.getGender(), "男") ? "1" : "0");})).collect(Collectors.toList());list.forEach(System.out::println);}@Testvoid contextLoads3() {AccountDTO accountDTO = new AccountDTO(1L,"test","123456","男","112@qq.com","user",new Date(),1);AccountDTO accountDTO2 = new AccountDTO(2L,"test2","123456","女","112@qq.com","admin",new Date(),0);Set<AccountDTO> accountDTOSet = new HashSet<>();accountDTOSet.add(accountDTO);accountDTOSet.add(accountDTO2);Set<AccountVO> set = accountDTOSet.stream().map(source -> source.asTargetObject(AccountVO.class, v-> {v.setGenderNum(Objects.equals(source.getGender(), "男") ? "1" : "0");})).collect(Collectors.toSet());set.forEach(System.out::println);}
}

实现步骤

1. dto 实现 BaseData接口
@Data
@AllArgsConstructor
@NoArgsConstructor
public class AccountDTO implements BaseData {private Long id;private String username;private String password;private String gender;private String email;private String role;private Date registerTime;private Integer isDelete;
}
2. dto.asViewObject(Target.class);
3. 如果 Target 还有其他字段 也可以自定义,例如测试用例中的genderNum(只是简单举的例子,按照项目实际来)
4. `isDelete` 这种is开头的也支持
1. 如果有问题,看下lombok版本是否有问题 此项目用的版本是 1.18.28 没问题
2. 如果没用lombok 手动加上getIsDelete() 用这个格式就可以了

注意

两个类 相同的字段名的字段类型 必须完全一样!!!

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Python】公众号聚合登录软件+源码

废话不多说了,直接上图,回复拿软件和源码【自己打包,配置环境比较复杂】 写这个软件就是因为其他平台的会员太贵了,还不如自己写个,不限制账号登录数~授权,打开和删除功能都是正常的, 面板功能,我打算做一个单独的页面【但是不知道做啥,就先放这里,希望各位老板提供想…

HuggingFace Transformers

HuggingFace Transformers https://www.hugging-face.org/hugging-face-transformers-2/Hugging Face Transformers has been built by, with, and for the community. Reaching 100k on GitHub is a testament to ML’s reach and the community’s will to innovate and cont…

函数式接口的使用

介绍 Consumer、Supplier、Predicate与Function 接口的使用Consumer 的使用(顾客) Consumer 翻译过来的意思就是消费者,很容易理解,它就是一个只负责消费的接口。相当于你是一个餐馆的顾客,你只负责吃你点的食物。在项目中一些不需要返回值,只负责消费的方法可以用过 Con…

Go语言之函数(func)进阶篇

目录一.init初始化函数1 初始化函数作用2 初始化函数定义案例2.1 初始化项目2.2 utils.go源代码2.3 main.go源代码二.匿名函数1 匿名函数概述2 匿名函数案例三.闭包函数1 闭包函数概述2 闭包函数案例之返回上级函数内部变量3 闭包函数案例之返回上级函数形参变量4 闭包函数返回…

linux命令入门指南

linux命令入门指南 (个人学习所用,雷同之处请忽略) 关于linux 服务器种类物理服务器 需要机房(零度、无尘、无静电)--防止机器短路,数据丢失。(建造自己的机房或者进行托管) 自己的服务器需要维护。 云服务器 由服务器厂商提供(阿里云、腾讯云)--省钱、有人维护 vmwa…

基于FPGA的MSK调制解调系统verilog开发,包含testbench,同步模块,高斯信道模拟模块,误码率统计模块

1.算法仿真效果 本程序系统是《m基于FPGA的MSK调制解调系统verilog开发,并带FPGA误码检测模块和matlab仿真程序》的的升级。升级前原文链接增加了完整的AWGN信道模型的FPGA实现,可以在testbench里面设置SNR,分析不同SNR对应的FPGA误码率情况。vivado2019.2仿真结果如下(完整…

【总结】逻辑运算在Z3中运用+CTF习题

国际赛IrisCTF在前几天举办,遇到了一道有意思的题目,特来总结。题目并不是很难,没有复杂的ollvm混淆也没有复杂的加密,但是却一步一步引导我们去学习和总结。国际赛IrisCTF在前几天举办,遇到了一道有意思的题目,特来总结。题目附件如下:📎babyrevjohnson.tar 解题过程…

在Python中使用SWCNN去除水印

在Python中使用SWCNN去除水印 说明首次发表日期:2024-07-17 SWCNN Github官方仓库: https://github.com/hellloxiaotian/SWCNN SWCNN 论文链接: https://arxiv.org/abs/2403.05807准备 运行环境 首先创建一个conda环境,安装SWCNN官方建议的库: conda create -n py39torch …

Xilinx NVMe AXI4主机控制器,AXI4接口高性能版本介绍

NVMe AXI4 Host Controller IP可以连接高速存储PCIe SSD,无需CPU,自动加速处理所有的NVMe协议命令,具备独立的数据写入和读取AXI4接口,不但适用高性能、顺序访问的应用,也适用于随机访问的应用,同时结合外部存储器(比如DDR),使得Host端的数据访问管理更加灵活。NVMe A…

请问如何将带有斜纹水印pdf的转成Excel呢?

大家好,我是Python进阶者。 一、前言 前几天在Python最强王者交流群【wen】问了一个Python自动化办公的问题,问题如下:请问如何将带有斜纹水印pdf的转成Excel呢?目前我把pdf转成图片,根据水印的颜色进行清除,但是在脱网环境下无法将图片转成Excel。 二、实现过程 后来【隔…

并发问题的三大根源是什么?

本文探讨了在多线程环境下,CPU缓存、线程切换以及编译优化如何影响数据的可见性、原子性和有序性,并提出了相应的解决方案。在单核CPU时代,所有线程共享同一缓存,确保了数据的一致性。然而,多核CPU下,各核心拥有独立缓存,可能导致线程间数据更新不可见。1.前言 从进程与…

判断语句

判断语句 猜猜心里数字:n=6 if int(input("第一次输入数字"))==n:print("猜对了") elif int(input("第二次输入数字"))==n:print("第二次猜对了") elif int(input("第三次输入数字"))==n:print("第三次对了") el…