写点什么

Java 常用对象映射工具的介绍和使用

作者:echoes
  • 2023-05-19
    福建
  • 本文字数:6260 字

    阅读完需:约 21 分钟

Java常用对象映射工具的介绍和使用

一、对象映射的概念和重要性

在现代软件开发中,经常需要处理不同类型的数据对象之间的转换和映射。对象映射是指将一个对象的数据映射到另一个对象上的过程。这个过程涉及将一个对象的属性值复制到另一个对象的对应属性上,以实现数据的传递和转换。

对象映射在很多场景下都非常重要。例如,在应用程序的不同层之间进行数据传递时,经常需要将数据库实体对象转换为领域对象(Domain Object),或者将领域对象转换为数据传输对象(Data Transfer Object,DTO)。此外,在不同服务之间进行通信时,也需要进行对象之间的映射。

二、常用的 Java 对象映射工具

常用的 Java 对象映射工具,如 ModelMapper、Dozer、MapStruct、Orika 和 Apache Commons BeanUtils

1、MapStruct

它是一个基于注解的代码生成器,可以根据定义的映射规则自动生成对象之间的映射代码。下面我们来详细介绍 MapStruct。

MapStruct

  • 概述: MapStruct 是一个用于简化 Java 对象映射的注解处理器。它根据定义的映射规则生成类型安全的映射代码,减少手动编写重复且容易出错的映射代码的工作量。

  • 优点:

    强类型安全:MapStruct 通过编译时生成映射代码,保证类型安全,避免在运行时出现类型转换错误。

    易于使用:通过简单的注解配置和约定,可以轻松定义映射规则,无需手动编写大量的映射代码。

    高性能:MapStruct 生成的映射代码经过优化,执行效率高,能够处理大规模的对象映射。

    可扩展性:MapStruct 具有灵活的插件机制,可以根据需要进行扩展和自定义。

  • 适用场景:

    对象之间存在结构相似但字段命名不同的映射需求。

    需要频繁进行复杂对象之间的映射,减少手动编写大量重复代码的工作量。

    希望通过编译时生成映射代码,提高运行时的性能和类型安全性。

  • 使用方式:

  • 引入依赖:在项目的构建文件中添加 MapStruct 的依赖,例如使用 Maven 的话,在 pom.xml 文件中添加以下依赖配置:

<dependency>    <groupId>org.mapstruct</groupId>    <artifactId>mapstruct</artifactId>    <version>1.4.2.Final</version></dependency>
复制代码
  • 定义映射接口:创建一个 Java 接口,使用 @Mapper 注解标注该接口,并配置映射规则,如字段名、类型转换等。

import org.mapstruct.Mapper;import org.mapstruct.Mapping;
@Mapperpublic interface ObjectMapper { DestinationObject mapToDestination(SourceObject source);}
复制代码
  • 生成映射实现类:编译项目后,MapStruct 将会根据定义的接口生成对应的映射实现类,无需手动编写映射代码。

  • 使用映射实现类:通过映射实现类进行对象的转换。

  • 示例代码:

// 假设有以下两个类,需要进行对象映射public class SourceObject {    private String name;    private int age;    // 省略构造函数、getter和setter方法}
public class DestinationObject { private String fullName; private int years; // 省略构造函数、getter和setter方法}
// 定义映射接口@Mapperpublic interface ObjectMapper { @Mapping(source = "name", target = "fullName") @Mapping(source = "age", target = "years") DestinationObject mapToDestination(SourceObject source);}
// 生成映射实现类ObjectMapper mapper = new ObjectMapperImpl(); // 自动生成的映射实现类的实例
// 使用映射实现类进行对象转换SourceObject source = new SourceObject("John Doe", 30);DestinationObject destination = mapper.mapToDestination(source);
// 打印转换结果System.out.println(destination.getFullName()); // 输出:John DoeSystem.out.println(destination.getYears()); // 输出:30
复制代码

上述示例中,我们定义了 SourceObjectDestinationObject 两个类,它们的字段名不完全相同。然后我们创建了一个映射接口 ObjectMapper 并使用 @Mapper 注解标注。在映射接口中,我们使用 @Mapping 注解指定字段的映射关系。最后,通过映射实现类的实例进行对象转换,将 SourceObject 转换为 DestinationObject,并打印转换结果。

MapStruct 的优点在于它能够根据定义的映射规则自动生成映射代码,简化了对象之间的转换过程,提高了开发效率。它适用于对象之间存在结构相似但字段命名不同的映射需求,并且希望通过编译时生成映射代码来提高运行时的性能和类型安全性的场景。


2、ModelMapper

ModelMapper 是一个优秀的 Java 对象映射工具,它提供了简洁而强大的功能来进行对象之间的转换。与 MapStruct 不同,ModelMapper 更加灵活,可以处理更复杂的映射场景。

  • 使用方式

  • 引入 ModelMapper 依赖:首先,在你的项目中添加 ModelMapper 的依赖,可以通过 Maven 或 Gradle 进行引入。

<!-- Maven 依赖 --><dependency>    <groupId>org.modelmapper</groupId>    <artifactId>modelmapper</artifactId>    <version>2.4.4</version></dependency>
复制代码


  • 创建 ModelMapper 实例:在代码中创建 ModelMapper 的实例,可以使用默认的构造函数创建。

ModelMapper modelMapper = new ModelMapper();
复制代码


  • 配置映射规则:可以使用 ModelMapper 提供的一些配置选项来自定义映射规则,如字段名称不匹配时的映射策略、忽略特定字段等。

modelMapper.getConfiguration()    .setMatchingStrategy(MatchingStrategies.STRICT)    .setFieldMatchingEnabled(true)    .setSkipNullEnabled(true);
复制代码

在上述示例中,我们使用 setMatchingStrategy 设置严格的字段匹配策略,setFieldMatchingEnabled 开启字段匹配,setSkipNullEnabled 允许跳过空值字段。

  • 自定义映射规则

如果需要对某些属性进行自定义映射,可以在 ModelMapper 实例上使用 addMappings() 方法定义映射规则。

javaCopy codemodelMapper.addMappings(new PropertyMap<SourceObject, TargetObject>() {    @Override    protected void configure() {        map().setName(source.getName().toUpperCase());        map().setAge(source.getAge() + 1);    }});
复制代码

在上面的示例中,我们自定义了映射规则,将源对象的名称转换为大写,并将年龄加 1 后映射到目标对象中。

  • 执行对象转换:使用 ModelMapper 的 map 方法进行对象之间的转换。

SourceObject source = new SourceObject();source.setName("John Doe");source.setAge(30);
DestinationObject destination = modelMapper.map(source, DestinationObject.class);
复制代码

在上述示例中,我们创建了一个 ModelMapper 的实例,并使用 map 方法将 SourceObject 转换为 DestinationObject。ModelMapper 会自动发现对象之间的属性映射关系,并执行转换。

ModelMapper 的优点在于它的灵活性和强大的功能。它支持复杂的映射场景,并提供了丰富的配置选项,使开发者能够自定义映射规则和转换行为。它适用于需要更多控制和自定义的对象映射场景

3、Dozer

Dozer 是一个功能强大的 Java 对象映射工具,它提供了简单而灵活的方式来进行对象之间的转换。Dozer 的主要目标是提供零配置的对象映射,使得开发者能够轻松地进行对象转换。

  • 使用 Dozer 有以下几个步骤

  • 添加 Dozer 依赖:首先,在你的项目中添加 Dozer 的依赖,可以通过 Maven 或 Gradle 进行引入。

<!-- Maven 依赖 --><dependency>    <groupId>net.sf.dozer</groupId>    <artifactId>dozer</artifactId>    <version>5.5.1</version></dependency>
复制代码


  • 创建 DozerBeanMapper 实例:在代码中创建 DozerBeanMapper 的实例,可以使用默认的构造函数创建。

javaCopy codeDozerBeanMapper mapper = new DozerBeanMapper();
复制代码
  • 配置映射规则:Dozer 支持多种方式配置映射规则,包括 XML 配置文件、注解和编程方式。你可以选择其中一种方式来定义对象之间的属性映射关系。

javaCopy code// 使用 XML 配置文件配置映射规则mapper.setMappingFiles(Arrays.asList("dozer-config.xml"));
// 使用注解配置映射规则@Mapping("sourceField")private String destinationField;
// 使用编程方式配置映射规则mapper.addMapping(new BeanMappingBuilder() { protected void configure() { mapping(SourceClass.class, DestinationClass.class) .fields("sourceField", "destinationField"); }});
复制代码

具体规则配置:

1、定义 Dozer 的 XML 映射规则:创建一个 XML 配置文件,定义源对象和目标对象之间的映射规则。例如,创建名为 dozer-config.xml 的配置文件,并在其中定义映射规则。

<?xml version="1.0" encoding="UTF-8"?><mappings xmlns="http://dozermapper.github.io/schema/bean-mapping" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://dozermapper.github.io/schema/bean-mapping http://dozermapper.github.io/schema/bean-mapping.xsd">    <mapping>        <class-a>com.example.SourceObject</class-a>        <class-b>com.example.TargetObject</class-b>        <field>            <a>name</a>            <b>fullName</b>        </field>        <field>            <a>age</a>            <b>years</b>        </field>    </mapping></mappings>
复制代码

在上述示例中,我们定义了一个源对象 SourceObject 和目标对象 TargetObject 之间的映射规则,将源对象的 name 属性映射到目标对象的 fullName 属性,将 age 属性映射到 years 属性。

2、注解来定义映射规则

在源对象和目标对象的类定义上添加注解 @Mapping,指定属性之间的映射关系。

public class SourceObject {    @Mapping("fullName")    private String name;
@Mapping("years") private int age;
// 省略其他属性和方法}
public class TargetObject { private String fullName; private int years;
// 省略其他属性和方法}
复制代码

在上述示例中,我们在源对象 SourceObjectname 属性上添加了 @Mapping("fullName") 注解,将其映射到目标对象 TargetObjectfullName 属性。同样地,我们在源对象的 age 属性上添加了 @Mapping("years") 注解,将其映射到目标对象的 years 属性。

使用注解配置映射规则相比于 XML 配置文件,可以更直观地在类定义中看到属性之间的映射关系,并且减少了额外的配置文件。

3、编程方式进行映射规则

创建 DozerMapper 实例,并进行映射规则的编程配置。

DozerBeanMapper mapper = new DozerBeanMapper();
mapper.addMapping(new BeanMappingBuilder() { @Override protected void configure() { mapping(SourceObject.class, TargetObject.class) .fields("name", "fullName") .fields("age", "years"); }});
复制代码

在上述示例中,我们通过 addMapping() 方法添加了一个 BeanMappingBuilder 实例,并在其 configure() 方法中进行映射规则的编程配置。使用 fields() 方法来指定源对象和目标对象的属性之间的映射关系。

使用编程方式配置映射规则允许更灵活地在代码中进行映射规则的定义,可以根据具体的需求进行动态的配置和映射规则的定制


  • 执行对象转换:使用 DozerBeanMapper 的 map 方法进行对象之间的转换。

javaCopy codeSourceObject source = new SourceObject();source.setName("John Doe");source.setAge(30);
DestinationObject destination = mapper.map(source, DestinationObject.class);
复制代码

在上述示例中,我们创建了一个 DozerBeanMapper 的实例,并使用 map 方法将 SourceObject 转换为 DestinationObject。Dozer 会根据配置的映射规则自动进行对象属性的复制。

Dozer 的优点在于它的零配置和简单易用。它可以根据对象之间的命名约定自动进行映射,减少了繁琐的手动配置。Dozer 适用于简单的对象映射场景,并且可以快速上手。

4、BeanUtils

Apache Commons BeanUtils 是一个开源的 Java 库,提供了简单而灵活的方式来进行 JavaBean 之间的属性复制和转换。它可以方便地进行对象之间的属性赋值,省去了手动编写大量的属性赋值代码的工作。

  • 使用 Apache Commons BeanUtils 有以下几个步骤:

  • 添加 Apache Commons BeanUtils 依赖:首先,在你的项目中添加 Apache Commons BeanUtils 的依赖,可以通过 Maven 或 Gradle 进行引入。

xmlCopy code<!-- Maven 依赖 --><dependency>    <groupId>commons-beanutils</groupId>    <artifactId>commons-beanutils</artifactId>    <version>1.9.4</version></dependency>
复制代码
  • 导入相关类:在代码中导入需要使用的 Apache Commons BeanUtils 类。

javaCopy codeimport org.apache.commons.beanutils.BeanUtils;import org.apache.commons.beanutils.PropertyUtils;
复制代码
  • 执行属性复制:使用 BeanUtils 的 copyProperties 方法进行属性复制。

javaCopy codeSourceObject source = new SourceObject();source.setName("John Doe");source.setAge(30);
DestinationObject destination = new DestinationObject();BeanUtils.copyProperties(destination, source);
复制代码

在上述示例中,我们创建了一个 SourceObject 对象和一个空的 DestinationObject 对象,然后使用 BeanUtils.copyProperties 方法将 SourceObject 的属性复制到 DestinationObject 中。

除了属性复制外,Apache Commons BeanUtils 还提供了其他一些实用的方法,比如获取属性值、设置属性值、调用方法等。

Apache Commons BeanUtils 的优点在于它的简单易用和丰富的功能。它提供了许多实用的方法来处理对象属性,可以快速实现对象之间的属性复制和转换。

5、Orika

Orika 是一个简单而强大的 Java 对象映射工具,它提供了高性能的对象之间的属性复制和转换功能。Orika 的目标是通过简单的配置和代码,实现快速、灵活和可扩展的对象映射。

  • 使用 Orika 有以下几个步骤

  • 添加 Orika 依赖:首先,在你的项目中添加 Orika 的依赖,可以通过 Maven 或 Gradle 进行引入。

xmlCopy code<!-- Maven 依赖 --><dependency>    <groupId>ma.glasnost.orika</groupId>    <artifactId>orika-core</artifactId>    <version>1.5.4</version></dependency>
复制代码
  • 定义对象映射配置:使用 Orika 的 MapperFactory 创建一个 MapperFacade,并配置对象之间的映射关系。

javaCopy codeMapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();mapperFactory.classMap(SourceClass.class, DestinationClass.class)    .field("sourceField", "destinationField")    .byDefault()    .register();MapperFacade mapper = mapperFactory.getMapperFacade();
复制代码

在上述示例中,我们创建了一个 MapperFactory,并使用 classMap 方法定义了 SourceClassDestinationClass 之间的映射关系。通过 field 方法指定了属性之间的映射,然后使用 byDefault 方法指定了默认的映射规则。最后,通过 register 方法注册映射配置。

  • 执行属性复制:使用 MapperFacade 的 map 方法进行属性复制。

javaCopy codeSourceClass source = new SourceClass();source.setSourceField("Hello");
DestinationClass destination = mapper.map(source, DestinationClass.class);
复制代码

在上述示例中,我们创建了一个 SourceClass 对象,并设置了一个属性值。然后使用 MapperFacade 的 map 方法将 SourceClass 的属性复制到 DestinationClass 中。

Orika 提供了许多高级功能,比如字段级别的映射配置、自定义转换器、深度映射等。它还支持集合、数组和嵌套对象的映射。

Orika 的优点在于它的高性能、简单易用和丰富的功能。它通过简单的配置和代码,实现了快速和灵活的对象映射。

三、总结


发布于: 2023-05-19阅读数: 26
用户头像

echoes

关注

探索未知,分享收获 2018-04-25 加入

还未添加个人简介

评论

发布
暂无评论
Java常用对象映射工具的介绍和使用_echoes_InfoQ写作社区