广告
返回顶部
首页 > 资讯 > 后端开发 > Python >Java MapStruct解了对象映射的毒
  • 680
分享到

Java MapStruct解了对象映射的毒

2024-04-02 19:04:59 680人浏览 安东尼

Python 官方文档:入门教程 => 点击学习

摘要

目录前言介绍代码编写探个究竟结尾前言 mvc模式是目前主流项目的标准开发模式,这种模式下框架的分层结构清晰,主要分为Controller,Service,Dao。分层的结构下,各层之

前言

mvc模式是目前主流项目的标准开发模式,这种模式下框架的分层结构清晰,主要分为Controller,Service,Dao。分层的结构下,各层之间的数据传输要求就会存在差异,我们不能用一个对象来贯穿3层,这样不符合开发规范且不够灵活。

我们常常会遇到层级之间字段格式需求不一致的情况,例如数据库中某个字段是datetime日期格式,这个时间戳在数据库中的存储值为2020-11-06 23:59:59.999999,但是传递给前端的时候要求接口返回yyyy-MM-dd的格式,或者有些数据在数据库中是逗号拼接的String类型,但是前端需要的是切割后的List类型等等。

所以我们提出了层级间的对象模型,就是我们常见的VO,DTO,DO,PO等等。这种区分层级对象模型的方式虽然清晰化了我们各层级间的对象传递,但是对象模型间的相互转换和值拷贝确是让人感觉很麻烦,拷贝来拷贝去,来来回回,过程重复乏味,编写此类映射代码是一项繁琐且容易出错的任务。

最简单粗糙的拷贝方法就是不断的new对象然后对象间的 setter 和 getter,这种方式应对字段属性少的还可以,如果属性字段很多那么大段的set,get的代码就显得很不雅美。因此需要借助对象拷贝工具,目前市场上的也蛮多的像BeanCopy,Dozer等等,但是这些我感觉都不够好,今天我推荐一个实体映射工具就是 MapStruct。

介绍

MapStruct的官网地址是 https://mapstruct.org/MapStruct,是一个快速安全的bean 映射代码生成器,只需要通过简单的注解就可以实现对象间的属性转换,是一款 Apache LICENSE 2.0 授权的开源产品,GitHub源码地址是 Https://github.com/mapstruct。

通过官网的三连问(What,Why,How)我们可以大概的了解到 MapStruct 的作用,它的优势以及它是如何实现的。

从上面的三连问中我们可以得到如下信息:

  • 基于约定优于配置的方法 MapStruct 极大地简化了 Java bean 类型之间的映射的实现,通过简单的注解就可以工作。生成的映射代码使用普通的方法调用而不是反射,因此速度快,类型安全且易于理解。
  • 在编译时生成 Bean 映射 与其他映射框架相比,MapStruct 在编译时生成 Bean 映射,这样可以确保高性能,而且开发人员可以快速的得到反馈和彻底的错误检查。
  • 一个注释处理器 MapStruct 是一个注释处理器,已插入 Java 编译器,可用于命令行构建(Maven,Gradle等),也可用于您首选的IDE中(idea,Eclipse等)。

代码编写

MapStruct 需要 Java 1.8或更高版本。对于Maven-based 的项目,在pom 文件中添加如下依赖即可


<!-- 指定版本-->
<properties>
    <org.mapstruct.version>1.4.1.Final</org.mapstruct.version>
</properties>
<!-- 添加依赖 -->
<dependencies>
   <dependency>
	<groupId>org.mapstruct</groupId>
	<artifactId>mapstruct</artifactId>
	<version>${org.mapstruct.version}</version>
   </dependency>
   <dependency>
	<groupId>org.mapstruct</groupId>
	<artifactId>mapstruct-processor</artifactId>
	<version>${org.mapstruct.version}</version>
   </dependency>
</dependencies>

基本的依赖引入后就可以编写代码了,简单的定义一个映射类,为了与 mybatis中的 mapper 接口区分,我们可以取名为 xxObjectConverter

例如汽车对象的映射类名为 CarObjectConverter,我们有两个对象模型 DO 和 DTO,它们内部的属性字段如下:

数据库对应的持久化对象模型 CarDo


public class Car {
    @apiModelProperty(value = "主键id")
    private Long id;
	
    @ApiModelProperty(value = "制造商")
    private String manufacturers;
	
    @ApiModelProperty(value = "销售渠道")
    private String saleChannel;

    @ApiModelProperty(value = "生产日期")
    private Date productionDate;
    ...
}

层级间传输的对象模型 CarDto


public class CarDto {
    @ApiModelProperty(value = "主键id")
    private Long id;
	
    @ApiModelProperty(value = "制造商")
    private String maker;
	
    @ApiModelProperty(value = "销售渠道")
    private List<Integer> saleChannel;

    @ApiModelProperty(value = "生产日期")
    private Date productionDate;
    ...
}

再编写具体的 MapStruct 对象映射器


@Mapper
public interface CarObjectConverter{

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

    @Mapping(target = "maker", source = "manufacturers")
    CarDto carToCarDto(Car car);

}

对于字段名相同的可以不用额外的指定映射规则,但是字段名不同的属性则需要指出字段的映射规则,如上我们持久层 DO 的制造商的字段名是manufacturers 而层级间传输的DTO模型中则是maker,我们就需要在映射方法上通过@Mapping注解指出映射规则,我个人习惯是喜欢将target写在前面,source写在后面,这样是与映射对象的位置保持一致,差异字段多的时候方便对比且不易混淆。

开发过程中还会经常遇到一些日期格式的转换,就如开篇时说的那种,这时我们也可以指定日期的映射规则


@Mapper
public interface CarObjectConverter{

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

    @Mapping(target = "maker", source = "manufacturers")
    @Mapping(target = "productionDate", dateFORMat = "yyyy-MM-dd", source = "productionDate")
    CarDto carToCarDto(Car car);

}

这些都还是一些简单的字段的映射,但有时候我们两个对象模型间的字段类型不一致,如上汽车的销售渠道字段saleChannel,这个在数据库中是字符串逗号拼接的值1,2,3,而我们传递出去的需要是 List 的 Integer 类型,这种复杂的如何映射呢?

也是有方法的,我们先编写一个将字符串逗号分隔然后转成 List 的工具方法,如下


public class CollectionUtils {

    public static List<Integer> list2String(String str) {
        if (StringUtils.isNoneBlank(str)) {
            return Arrays.asList(str.split(",")).stream().map(s -> Integer.valueOf(s.trim())).collect(Collectors.toList());
        }
        return null;
    }
}

然后在映射Mapping中使用表达式即可


@Mapper
public interface CarObjectConverter {

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

    @Mapping(target = "maker", source = "manufacturers")
    @Mapping(target = "productionDate", dateFormat = "yyyy-MM-dd", source = "productionDate")
    @Mapping(target = "saleChannel", expression = "java(com.jiajian.demo.utils.CollectionUtils.list2String(car.getSaleChannel()))")
    CarDto carToCarDto(Car car);

}

这样就完成了所有字段的映射工作,我们在需要对象模型转换的地方按照如下方式调用即可


CarDto carDto = CarObjectConverter.INSTANCE.carToCarDto(car);

这种是单体对象之间的 Copy 很多时候我们需要 List 对象模型间的转换,只需要再写一个方法carToCarDtos即可


@Mapper
public interface CarObjectConverter{

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

    @Mapping(target = "maker", source = "manufacturers")
    @Mapping(target = "productionDate", dateFormat = "yyyy-MM-dd", source = "productionDate")
    @Mapping(target ="saleChannel", expression = "java(com.jiajian.demo.utils.CollectionUtils.list2String(car.getSaleChannel()))")
    CarDto carToCarDto(Car car);

    List<CarDto> carToCarDtos(List<Car> carList);

}

探个究竟

会不会好奇这是怎么实现的,我们只是创建了一个接口然后在接口方法上加一个注解并在注解里面指定字段的映射规则就可以实现对象属性间的拷贝,这是怎么做到的呢?

我们这里通过 MapStruct 创建的只是一个接口,要实现具体的功能接口必有实现。

MapStruct 会在我们代码编译的时候为我们创建一个实现类,而这个实现类里面通过字段的setter, getter方法来实现字段的赋值,从而实现对象的映射。

这里需要注意一点:如果你修改了任一映射对象,记得需要先执行mvn clean再启动项目,否则调试的时候会报错。

结尾

MapStrut 的功能远不至于上面介绍的这些,我只是挑出几个常用的语法进行示例讲解,如果读者感兴趣想深入的了解更多可以参考官方的参考文档

遇见 MapStruct 后我就开始在项目中抛弃掉了原来的那些 BeanCopyUtils 的工具,相对而言 MapStruct 确实更简洁且易使用而且定制功能也很强。

从编译文件可以看出 MapStruct 是通过setter,getter来实现属性值的拷贝,然后这种方式不是最简单又最安全高效的吗?只是 MapStruct 更好的帮助我们实现了,避免了项目中冗余的重复代码,大道至简。

以上就是MapStruct解了对象映射的毒的详细内容,更多关于MapStruct的资料请关注编程网其它相关文章!

--结束END--

本文标题: Java MapStruct解了对象映射的毒

本文链接: https://www.lsjlt.com/news/124402.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Java MapStruct解了对象映射的毒
    目录前言介绍代码编写探个究竟结尾前言 MVC模式是目前主流项目的标准开发模式,这种模式下框架的分层结构清晰,主要分为Controller,Service,Dao。分层的结构下,各层之...
    99+
    2022-11-12
  • 了解 Unix 对象和 Laravel 中的对象关系映射
    Unix对象和Laravel中的对象关系映射是两个非常重要的概念。在本篇文章中,我们将深入探讨这两个主题,以帮助您更好地了解它们的作用和用途。 Unix对象 Unix是一种操作系统,它使用对象来表示文件、目录和设备等概念。在Unix中,一切...
    99+
    2023-08-09
    laravel unix 对象
  • MapStruct对象映射转换解决Bean属性拷贝性能问题
    目录简介适用场景工作时机使用案例1、添加依赖2、定义两个类3、单元测试核心总结简介 MapStruct 是一个代码生成器(可以生成对象映射转换的代码),它基于约定优于配置的方法,极大...
    99+
    2022-11-13
  • @RequestBody不能映射到对象的解决
    目录@RequestBody不能映射到对象解决方法@RequestBody使用方法(将数据映射到java对象上)1.请求方式如下2.对象定义如下3.可以看到,json数据映射到Use...
    99+
    2022-11-12
  • 详解Java对象转换神器MapStruct库的使用
    目录前言MapStruct简介MapStruct入门1. 引入依赖2. 需要转换的对象3. 创建转换器4. 验证5. 自动生成的实现类MapStruct进阶场景1:属性名称不同、(基...
    99+
    2022-11-13
  • 【Java 基础篇】Java反射:深入了解Class对象
    Java是一门强类型语言,它要求在编译时知道所有的类和对象类型。然而,有时候我们需要在运行时动态地获取和操作类的信息,这就是Java反射的用武之地。本文将深入探讨Java反射,特别是与Class对象...
    99+
    2023-10-27
    java python 开发语言 ajax 网络 eclipse git 原力计划
  • JavaScript策略模式利用对象键值的映射关系详解
    目录引言1、策略模式的极简实现2.策略模式的简单案例(1)工具函数(2)提示样式总结引言 策略模式指的是,定义一系列的算法,把它们一个个的封装起来,通过传递一些参数,使他们可以相互...
    99+
    2022-12-22
    JavaScript策略模式对象键值映射 JavaScript 策略模式
  • 深入了解java中的string对象
    这里来对Java中的String对象做一个稍微深入的了解。Java对象实现的演进String对象是Java中使用最频繁的对象之一,所以Java开发者们也在不断地对String对象的实现进行优化,以便提升String对象的性能。(推荐学习:J...
    99+
    2019-07-17
    java教程 java string
  • 带你了解Java的类和对象
    目录五丶封装(1)包的概念与创建1>概念2>创建(2)包的使用–导入包(3)封装定义–权限控制访问(4)补充些常用的包(小拓展)六丶关于static成员(1)修饰成员变量...
    99+
    2022-11-12
  • 深入了解Java File对象的使用
    目录1.File对象 2.创建文件3.文件的相关操作1.File对象  java封装的一个操作文件及文件夹(目录)的对象。可以操作磁盘上的任何一个文件和文件夹。 2.创建文件 方式一...
    99+
    2022-11-13
    Java File对象 Java File
  • Java面向对象的封装你了解吗
    目录面向对象思想之封装什么是封装呢?封装的好处意义getter方法和setter方法toString方法总结:面向对象思想之封装 或许大家都听说过java是纯面向对象语言,面向对象思...
    99+
    2022-11-13
  • Java 用反射设置对象的属性值实例详解
    Java 用反射设置对象的属性值实例详解private Object invoke(Object obj, String fieldName, Object value) { String firstWord = fieldName.su...
    99+
    2023-05-31
    java 反射 对象
  • 带你快速了解Java中类和对象的关系
    本文重点解读Java里的类和对象的关系 1、首先介绍两个概念 类:类是对现实生活中一类具有共同属性和行为事务的抽象,确定对象将会拥有的属性和行为。 对象:对象是类的一个实例(对象不...
    99+
    2022-11-12
  • Spring容器中的Java对象存储问题:你了解多少?
    Spring作为一个非常流行的Java开发框架,提供了很多便利的功能和特性,其中就包括了Spring容器。Spring容器是一个非常重要的概念,它的作用是管理Java对象的创建、初始化、销毁等操作。在使用Spring框架的过程中,我们不可避...
    99+
    2023-11-02
    存储 spring 容器
  • 你了解 Java 对象在 HTTP 加载时的工作原理吗?
    Java 对象在 HTTP 加载时的工作原理 在 Java 中,对象是一种非常重要的概念。随着 Web 技术的发展,HTTP 协议成为了 Web 应用程序中最常用的协议之一。在 Web 应用程序中,Java 对象在 HTTP 加载时的工作原...
    99+
    2023-07-27
    对象 http load
  • 你了解Java中对象异步编程的最佳实践吗?
    当今互联网应用越来越复杂,而Java作为一种广泛使用的编程语言,对象异步编程已经成为Java编程中一个必不可少的环节。本文将介绍Java中对象异步编程的最佳实践,并给出一些演示代码,帮助Java开发者更好地理解和应用异步编程。 一、什么是对...
    99+
    2023-07-19
    对象 异步编程 并发
  • Java大数据处理中的对象加载问题你了解吗?
    随着大数据时代的到来,数据处理变得越来越复杂,而Java作为一种广泛应用于企业级应用程序的语言,也必须应对大数据处理方面的挑战。在处理大数据时,Java程序需要加载大量的对象,因此对象加载的效率成为了一个关键问题。本文将介绍Java大数据...
    99+
    2023-08-16
    大数据 对象 load
  • Java中的自然语言处理:了解Apache对象的工作原理
    自然语言处理(NLP)是人工智能领域中的一个研究方向,它旨在让计算机理解和处理自然语言,包括文本和语音。随着自然语言处理技术的不断发展,越来越多的企业开始意识到它的重要性,尤其是在处理大量文本数据时。Apache对象是Java中一个非常流...
    99+
    2023-08-29
    自然语言处理 对象 apache
  • 了解Java编程中的对象和API,从而提高算法效率!
    Java是一种面向对象的编程语言,它允许程序员创建对象来表示现实世界中的事物,并使用这些对象来编写程序。Java的API(Application Programming Interface)是一个强大的工具,可以帮助程序员编写高效的代码,提...
    99+
    2023-10-24
    对象 编程算法 api
  • Spring容器中Java对象存储的最佳实践:你了解多少?
    Spring作为一个开源的轻量级Java应用框架,其提供了一个强大的容器来管理应用中的Java对象。而这个容器在使用中,也有一些存储的最佳实践需要我们遵循。本文将介绍Spring容器中Java对象存储的最佳实践,并演示代码来加深理解。 一、...
    99+
    2023-11-02
    存储 spring 容器
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作