0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

MapStruct中的高级特性使用

jf_ro2CN3Fa 来源:芋道源码 2023-05-26 15:59 次阅读

事件回顾

分析探讨

推荐方案

总结

44ca47fa-fafb-11ed-90ce-dac502259ad0.jpg

前言

最近项目上要求升级一个工具包hutool的版本,以解决安全漏洞问题,这不升级还好,一升级反而捅出了更大的篓子,究竟是怎么回事呢?

基于 Spring Boot + MyBatis Plus + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能

项目地址:https://github.com/YunaiV/ruoyi-vue-pro

视频教程:https://doc.iocoder.cn/video/

事件回顾

我们项目原先使用的hutool版本是5.7.2,在代码中,我们的数据传输对象DTO和数据实体对象中大量使用了工具包中的BeanUtil.copyProperties(), 大体代码如下:

数据传输对象

@Data
@ToString
publicclassDiagramDTO{

//前端生产的字符串id
privateStringid;

privateStringcode;

privateStringname;
}

数据实体对象

@Data
@ToString
publicclassDiagram{

privateIntegerid;

privateStringcode;

privateStringname;
}

业务逻辑

publicclassBeanCopyTest{

publicstaticvoidmain(String[]args){
//前端传输的对象
DiagramDTOdiagramDTO=newDiagramDTO();
//如果前端传入的id事包含e的,升级后就会报错
diagramDTO.setId("3em3dgqsgmn0");
diagramDTO.setCode("d1");
diagramDTO.setName("图表");

Diagramdiagram=newDiagram();
//关键点,数据拷贝
BeanUtil.copyProperties(diagramDTO,diagram);
System.out.println("数据实体对象:"+diagram);
//设置id为空,自增
diagram.setId(null);
//保存到数据库中TODO
//diagramMapper.save(diagram);
}
}

升级前,hutool是5.7.2版本下,执行结果如下图。

44d670de-fafb-11ed-90ce-dac502259ad0.png

BeanUtil.copyProperties虽然字段类型不一样,但是做了兼容处理,所以业务没有影响业务逻辑。

升级后,hutool是5.8.8版本,执行结果如下图所示:

44e28d92-fafb-11ed-90ce-dac502259ad0.png

执行报错,因为升级后的版本修改了实现,增加了下面的逻辑,如果包含E, 就会抛错,从而影响了业务逻辑,同时这个id是否包含e又是随机因素,到了生产才发现,就悲剧了。

44f0d21c-fafb-11ed-90ce-dac502259ad0.png

基于 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能

项目地址:https://github.com/YunaiV/yudao-cloud

视频教程:https://doc.iocoder.cn/video/

分析探讨

我发现大部分人写代码都喜欢偷懒,在上面的场景中,虽然BeanUtil.copyProperties用的一时爽,但有时候带来的后果是很严重的,所以很不推荐这种方式。为什么这么说呢?

比如团队中的某些人偷偷改了数据传输对象DTO,比如修改了类型、删去了某个字段。用BeanUtil.copyProperties的方式压根无法在编译阶段发现,更别提修改的影响范围了,这就只能把风险暴露到生产上去了。那有什么更好的方法呢?

推荐方案

原始的get、set方式

我是比较推崇这种做法的,比如现在DiagramDTO删去某个字段,编译器就会报错,就会引起你的注意了,让问题提前暴露,无处遁形。

44fc19ba-fafb-11ed-90ce-dac502259ad0.png

你可能觉得站着说话不腰疼,字段少好,如果字段很多还不得写死啊,我这里推荐一个IDEA的插件,可以帮你智能生成这样的代码。

450bdb98-fafb-11ed-90ce-dac502259ad0.png45126594-fafb-11ed-90ce-dac502259ad0.png

话不多说,自己玩儿去~~

使用开源库ModelMapper

ModelMapper是一个开源库,可以很方便、简单地将对象从一种类型映射到另一种类型,底层是通过反射来自动确定对象之间的映射,还可以自定义映射规则。

privatestaticvoidtestModelMapper(){
ModelMappermodelMapper=newModelMapper();
DiagramDTOdiagramDTO=newDiagramDTO();
diagramDTO.setId("3em3dgqsgmn0");
diagramDTO.setCode("d1");
diagramDTO.setName("图表");
Diagramdiagram=modelMapper.map(diagramDTO,Diagram.class);
}

使用开源库MapStruct

MapStruct也是Java中另外一个用于映射对象很流行的开源工具。它是在编译阶段生成对应的映射代码,相对于ModelMapper底层放射的方案,性能更好。

@Mapper
publicinterfaceDiagramMapper{
DiagramMapperINSTANCE=Mappers.getMapper(DiagramMapper.class);

DiagramDTOtoDTO(Diagramdiagram);

DiagramtoEntity(DiagramDTOdiagram);
}

privatestaticvoidtestMapStruct(){
DiagramDTOdiagramDTO=newDiagramDTO();
diagramDTO.setId("3em3dgqsgmn0");
diagramDTO.setCode("d1");
diagramDTO.setName("图表");
Diagramdiagram=DiagramMapper.INSTANCE.toEntity(diagramDTO);
}

DiagramMapper接口使用了@Mapper注解,用来表明使用MapStruct处理

MapStruct中更多高级特性大家自己探索一下。

总结

小结一下,对象在不同层之间进行转换映射,很不建议使用BeanUtil.copyProperties这种方式,更加推荐使用原生的set, get方式,不容易出错。当然这不是将BeanUtil.copyProperties一棒子打死,毫无用武之地,在特定场景,比如方法内部对象的转换等影响小的范围还是很方便的。

审核编辑:彭静
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 代码
    +关注

    关注

    30

    文章

    4780

    浏览量

    68527
  • 编译
    +关注

    关注

    0

    文章

    657

    浏览量

    32852

原文标题:麻了!不要再动不动就用BeanUtil.copyProperties了!!

文章出处:【微信号:芋道源码,微信公众号:芋道源码】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    Python高级特性:迭代器切片的应用

    是 Python 独特的一种高级特性,而切片也是一种高级特性,两者相结合,会产生什么样的结果呢? 1、迭代与迭代器 首先,有几个基本概念要
    发表于 11-29 10:11 662次阅读

    对象转换工具:MapStruct

    在我们日常开发的程序,为了各层之间解耦,一般会定义不同的对象用来在不同层之间传递数据,比如xxxDTO、xxxVO、xxxQO,当在不同层之间传输数据时,不可避免地经常需要将这些对象进行
    的头像 发表于 10-08 14:39 1036次阅读

    16位高级控制定时器STM816有哪些特性

    STM816位高级控制定时器的主要特性
    发表于 11-16 07:23

    高级处理器特性能否提高编码效率?

    高级处理器特性能否提高编码效率?
    发表于 04-26 06:41

    高级控制定时器有哪些特性

    高级控制定时器和通用定时器有何功能?高级控制定时器有哪些特性呢?
    发表于 11-10 06:51

    LabVIEW调用DLL的高级技巧后续资源包

    1、LabVIEW调用DLL的高级技巧2、.NET InteropAssembly Builder3、LabVIEW机器人版
    发表于 07-01 08:28 209次下载

    Trace32的高级功能特性

    Trace32的高级功能特性 Logic analyzer Real-time Streaming and Profiling Boundary Scan Third Party Tools Intergrations Virtual Targets Debugging
    发表于 11-16 12:52 28次下载
    Trace32的<b class='flag-5'>高级</b>功能<b class='flag-5'>特性</b>

    在设计如何使用高级PCB模块

    添加高级 PCB 模块可以使 PADS Standard Plus 的功能更加强大。此模块物超所值,其中包含了高速自动布线、DFT 审核和高级封装功能。在此视频,我们将向您展示如何使用高级
    的头像 发表于 05-14 06:21 2037次阅读

    STMCube.AI的高级特性

    STM32CubeMX的功能。它还提供几种在桌面PC和STM32上验证神经网络模型以及测量模型性能的方法,而无需用户手工编写专门的C语言代码。 上一篇文章大致介绍了STMCube.AI的基本特性,以及其工作流程。 本文将更深入地介绍它的一些高级
    的头像 发表于 10-28 10:05 1992次阅读
    STMCube.AI的<b class='flag-5'>高级</b><b class='flag-5'>特性</b>

    STM32Cube.AI库的高级特性

    STM32CubeMX的功能。它还提供几种在桌面PC和STM32上验证神经网络模型以及测量模型性能的方法,而无需用户手工编写专门的C语言代码。 上一篇文章大致介绍了STMCube.AI的基本特性,以及其工作流程。 本文将更深入地介绍它的一些高级
    的头像 发表于 11-16 16:59 3102次阅读
    STM32Cube.AI库的<b class='flag-5'>高级</b><b class='flag-5'>特性</b>

    SOK将HugeCTR高级特性进行包装使用

    ),来将 HugeCTR 高级特性封装为 TensorFlow 可直接调用的形式,从而帮助用户在 TensorFlow 中直接使用 HugeCTR
    的头像 发表于 04-07 16:02 1266次阅读
    SOK将HugeCTR<b class='flag-5'>中</b>的<b class='flag-5'>高级</b><b class='flag-5'>特性</b>进行包装使用

    英特尔高级链路分析器全新混合行为模式,兼“双优”特性

    英特尔 Quartus Prime 设计软件的英特尔 高级链路分析器拥有全新特性。它除了支持英特尔 Stratix 10 TX 家族 E-Tile IBIS-AMI,提供封装支持,还拥有全新的通道查看器功能。
    发表于 01-31 14:44 306次阅读

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

    关于lombok和mapstruct的版本兼容问题多说几句,maven插件要使用3.6.0版本以上、lombok使用1.16.16版本以上,另外编译的lombok mapstruct的插件不要忘了加上。
    的头像 发表于 07-10 10:46 555次阅读
    别再用BeanUtils了,这款PO VO DTO转换神器不香么?

    如何在实际的代码中使Spring组件的特性

    首先,我们将探讨一些 Spring 框架 IOC(Inversion of Control)的高级特性,特别是组件扫描的相关知识。
    的头像 发表于 08-11 09:52 589次阅读
    如何在实际的代码中使Spring组件的<b class='flag-5'>特性</b>?

    Wilink8高级特性

    电子发烧友网站提供《Wilink8高级特性.pdf》资料免费下载
    发表于 11-08 15:58 0次下载
    Wilink8<b class='flag-5'>高级</b><b class='flag-5'>特性</b>