MapStruct 快速指南



MapStruct - 概述

MapStruct 是一个注释处理器,它被插入到 Java 编译器中。插入后,它可以被 Maven、Gradle 等命令行工具用来处理映射注释,在编译时创建 Mapper 类。

何时需要映射?

在多层应用程序中,数据对象用于从数据库中获取数据,而 UI 与模型进行交互。现在,需要将获取到数据模型中的数据映射到模型或 Java Bean,然后传递给 UI。请考虑以下情况。

与数据库连接的实体类。

StudentEntity.java

@Entity
class StudentEntity {
   String id;
   String name;
}

与 UI 连接的模型类。

Student.java

class Student {
   String id;
   String name;
}

MapStruct 如何工作?

MapStruct 使用注解自动化创建 Mapper 的过程,以将数据对象与模型对象映射。它在编译时创建 Mapper 实现,这有助于开发人员在开发过程中发现错误,并使其易于理解。例如 -

StudentMapper.java

@Mapper
class StudentMapper {
   StudentMapper INSTANCE = Mappers.getMapper( StudentMapper.class );   
   StudentEntity modelToEntity(Student student);
}

现在可以使用 StudentMapper.INSTANCE 轻松获取映射后的对象。

StudentEntity studentEntity = StudentMapper.INSTANCE.modelToEntity(student);

MapStruct - 环境设置

MapStruct 是一个基于 Java 的库,因此第一个要求是在您的机器上安装 JDK。

步骤 1 - 设置 Java 开发工具包 (JDK)

您可以从 Oracle 的 Java 网站下载最新版本的 SDK - Java SE 下载。 您将在下载的文件中找到安装 JDK 的说明,请按照给定的说明进行安装和配置设置。最后设置 PATH 和 JAVA_HOME 环境变量以引用包含 java 和 javac 的目录,通常分别为 java_install_dir/bin 和 java_install_dir。

如果您正在运行 Windows 并已将 JDK 安装在 C:\jdk-9.0.1 中,则必须将以下行放入 C:\autoexec.bat 文件中。

set PATH=C:\jdk-11.0.11\bin;%PATH% 
set JAVA_HOME=C:\jdk-11.0.11

或者,在 Windows NT/2000/XP 上,您需要右键单击“我的电脑”,选择“属性”→“高级”→“环境变量”。然后,您需要更新 PATH 值并单击“确定”按钮。

在 Unix(Solaris、Linux 等)上,如果 SDK 安装在 /usr/local/jdk-9.0.1 中并且您使用的是 C shell,则需要将以下内容放入 .cshrc 文件中。

setenv PATH /usr/local/jdk-11.0.11/bin:$PATH 
setenv JAVA_HOME /usr/local/jdk-11.0.11

或者,如果您使用的是集成开发环境 (IDE),例如 Borland JBuilder、Eclipse、IntelliJ IDEA 或 Sun ONE Studio,则需要编译并运行一个简单的程序以确认 IDE 知道您已将 Java 安装在何处。否则,您需要按照 IDE 文档中给出的说明进行正确的设置。

步骤 2 - 安装 mapstruct 库以及依赖项

MVNRepository 下载以下 jar 并将其用于您的类路径。

  • mapstruct-1.5.0.Beta1.jar

  • mapstruct-processor-1.5.0.Beta1.jar

确保您已正确设置此目录上的 CLASSPATH 变量,否则在运行应用程序时会遇到问题。

步骤 3 - 设置 Eclipse IDE

本教程中的所有示例均使用 Eclipse IDE 编写。因此,我们建议您应该在您的机器上安装最新版本的 Eclipse。

要安装 Eclipse IDE,请从 www.eclipse.org/downloads 下载最新的 Eclipse 二进制文件。下载安装后,将二进制分发版解压缩到方便的位置。例如,在 Windows 上的 C:\eclipse 中,或在 Linux/Unix 上的 /usr/local/eclipse 中,最后正确设置 PATH 变量。

可以通过在 Windows 机器上执行以下命令来启动 Eclipse,或者您可以简单地双击 eclipse.exe

%C:\eclipse\eclipse.exe 

可以通过在 Unix(Solaris、Linux 等)机器上执行以下命令来启动 Eclipse -

$/usr/local/eclipse/eclipse

成功启动后,如果一切正常,则应显示以下结果 -

Eclipse Home page

步骤 4 - 创建 Maven 项目

C:\MVN>mvn archetype:generate
-DgroupId = com.tutorialspoint.mapping 
-DartifactId = mapping 
-DarchetypeArtifactId = maven-archetype-quickstart 
-DinteractiveMode = false

它将创建一个 Maven 项目。现在更新 pom.xml 文件,如下所示 -

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
   <modelVersion>4.0.0</modelVersion>
   <groupId>com.tutorialspoint.mapping</groupId>
   <artifactId>mapping</artifactId>
   <packaging>jar</packaging>
   <version>1.0-SNAPSHOT</version>
   <name>mapping</name>
   <url>http://maven.apache.org</url>
   <dependencies>
      <dependency>
         <groupId>org.junit.jupiter</groupId>
         <artifactId>junit-jupiter-engine</artifactId>
         <version>5.0.0</version>
         <scope>test</scope>
      </dependency>
      <dependency>
         <groupId>org.mapstruct</groupId>
         <artifactId>mapstruct</artifactId>
         <version>1.5.0.Beta1</version>
      </dependency>
   </dependencies>
   <build>
      <plugins>
         <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.8.1</version>
            <configuration>
               <source>11</source> 
               <target>11</target> 
               <annotationProcessorPaths>
                  <path>
                     <groupId>org.mapstruct</groupId>
                     <artifactId>mapstruct-processor</artifactId>
                     <version>1.5.0.Beta1</version>
                  </path>
               </annotationProcessorPaths>
            </configuration>
         </plugin>
      </plugins>
   </build>
</project>

运行以下命令以更新 Maven 依赖项并构建项目。

mvn package

命令成功后。将基于 Maven 的项目作为 Maven 项目导入 Eclipse。其余的 Eclipse 将处理。

MapStruct - 基本映射

使用 Mapstruct 非常简单。要创建 Mapper,请在接口上使用 **org.mapstruct.Mapper** 注解。

@Mapper
public interface StudentMapper {...}

现在在接口中创建一个转换方法。

@Mapper
public interface StudentMapper {
   Student getModelFromEntity(StudentEntity student);
}

如果源对象和目标对象的属性名称相同,则这些属性将自动映射。如果属性名称不同,请使用 @Mapping 注解,如下所示 -

@Mapper
public interface StudentMapper {
   @Mapping(target="className", source="classVal")
   Student getModelFromEntity(StudentEntity student);
}

此处 className 是 Student 中的属性名称,一个目标对象,classVal 是 StudentEntity 中的属性名称,一个源对象。

示例

在 Eclipse 中打开在 环境设置 章节中创建的项目映射。

使用以下代码创建 Student.java -

Student.java

package com.tutorialspoint.model;

public class Student {
   private int id;
   private String name;
   private String className;

   public int getId() {
      return id;
   }
   public void setId(int id) {
      this.id = id;
   }
   public String getName() {
      return name;
   }
   public void setName(String name) {
      this.name = name;
   }
   public String getClassName() {
      return className;
   }
   public void setClassName(String className) {
      this.className = className;
   }
}

使用以下代码创建 Student.java -

StudentEntity.java

package com.tutorialspoint.entity;

public class StudentEntity {
   private int id;
   private String name;
   private String classVal;
   public int getId() {
      return id;
   }
   public void setId(int id) {
      this.id = id;
   }
   public String getName() {
      return name;
   }
   public void setName(String name) {
      this.name = name;
   }
   public String getClassVal() {
      return classVal;
   }
   public void setClassVal(String classVal) {
      this.classVal = classVal;
   }
}

使用以下代码创建 StudentMapper.java -

StudentMapper.java

package com.tutorialspoint.mapper;

import org.mapstruct.Mapper;
import org.mapstruct.Mapping;

import com.tutorialspoint.entity.StudentEntity;
import com.tutorialspoint.model.Student;

@Mapper
public interface StudentMapper {

   @Mapping(target="className", source="classVal")
   Student getModelFromEntity(StudentEntity student);

   @Mapping(target="classVal", source="className")
   StudentEntity getEntityFromModel(Student student);
}

使用以下代码创建 StudentMapperTest.java -

StudentMapperTest.java

package com.tutorialspoint.mapping;

import static org.junit.jupiter.api.Assertions.assertEquals;

import org.junit.jupiter.api.Test;
import org.mapstruct.factory.Mappers;

import com.tutorialspoint.entity.StudentEntity;
import com.tutorialspoint.mapper.StudentMapper;
import com.tutorialspoint.model.Student;

public class StudentMapperTest {

   private StudentMapper studentMapper
      = Mappers.getMapper(StudentMapper.class);

   @Test
   public void testEntityToModel() {
      StudentEntity entity = new StudentEntity();
      entity.setClassVal("X");
      entity.setName("John");
      entity.setId(1);

      Student model = studentMapper.getModelFromEntity(entity);

      assertEquals(entity.getClassVal(), model.getClassName());
      assertEquals(entity.getName(), model.getName());
      assertEquals(entity.getId(), model.getId());
   }

   @Test
   public void testModelToEntity() {
      Student model = new Student();
      model.setId(1);
      model.setName("John");
      model.setClassName("X");

      StudentEntity entity = studentMapper.getEntityFromModel(model);

      assertEquals(entity.getClassVal(), model.getClassName());
      assertEquals(entity.getName(), model.getName());
      assertEquals(entity.getId(), model.getId());
   }
}

运行以下命令测试映射。

mvn clean test

命令成功后。验证输出。

mvn clean test
[INFO] Scanning for projects...
...
[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ mapping ---
[INFO] Surefire report directory: \mvn\mapping\target\surefire-reports

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running com.tutorialspoint.mapping.StudentMapperTest
Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.004 sec
...

MapStruct - 自定义映射

我们还可以将自定义方法添加到使用 **org.mapstruct.Mapper** 注解创建的 Mapper 中。我们也可以创建抽象类而不是接口。Mapstruct 自动创建相应的 Mapper 类。

现在在接口中创建一个默认转换方法。

@Mapper
public interface StudentMapper {
   default Student getModelFromEntity(StudentEntity studentEntity){
      Student student = new Student();
      student.setId(studentEntity.getId());
      student.setName(studentEntity.getName());
      student.setClassName(studentEntity.getClassVal());
      return student;
   }
}

以类似的方式,我们也可以创建抽象类以及 Mapper。

@Mapper
public absgract class StudentMapper {
   Student getModelFromEntity(StudentEntity studentEntity){
      Student student = new Student();
      student.setId(studentEntity.getId());
      student.setName(studentEntity.getName());
      student.setClassName(studentEntity.getClassVal());
      return student;
   }
}

示例

在 Eclipse 中打开在 环境设置 章节中创建的项目 mediaPlayer。

使用以下代码创建 Student.java -

Student.java

package com.tutorialspoint.model;

public class Student {
   private int id;
   private String name;
   private String className;

   public int getId() {
      return id;
   }
   public void setId(int id) {
      this.id = id;
   }
   public String getName() {
      return name;
   }
   public void setName(String name) {
      this.name = name;
   }
   public String getClassName() {
      return className;
   }
   public void setClassName(String className) {
      this.className = className;
   }
}

使用以下代码创建 Student.java -

StudentEntity.java

package com.tutorialspoint.entity;

public class StudentEntity {
   private int id;
   private String name;
   private String classVal;
   public int getId() {
      return id;
   }
   public void setId(int id) {
      this.id = id;
   }
   public String getName() {
      return name;
   }
   public void setName(String name) {
      this.name = name;
   }
   public String getClassVal() {
      return classVal;
   }
   public void setClassVal(String classVal) {
      this.classVal = classVal;
   }
}

使用以下代码创建 StudentMapper.java -

StudentMapper.java

package com.tutorialspoint.mapper;

import org.mapstruct.Mapper;
import org.mapstruct.Mapping;

import com.tutorialspoint.entity.StudentEntity;
import com.tutorialspoint.model.Student;

@Mapper
public interface StudentMapper {

   default Student getModelFromEntity(StudentEntity studentEntity){
      Student student = new Student();
      student.setId(studentEntity.getId());
      student.setName(studentEntity.getName());
      student.setClassName(studentEntity.getClassVal());
      return student;
   }

   @Mapping(target="classVal", source="className")
   StudentEntity getEntityFromModel(Student student);
}

使用以下代码创建 StudentMapperTest.java -

StudentMapperTest.java

package com.tutorialspoint.mapping;

import static org.junit.jupiter.api.Assertions.assertEquals;

import org.junit.jupiter.api.Test;
import org.mapstruct.factory.Mappers;

import com.tutorialspoint.entity.StudentEntity;
import com.tutorialspoint.mapper.StudentMapper;
import com.tutorialspoint.model.Student;

public class StudentMapperTest {

   private StudentMapper studentMapper
      = Mappers.getMapper(StudentMapper.class);

   @Test
   public void testEntityToModel() {
      StudentEntity entity = new StudentEntity();
      entity.setClassVal("X");
      entity.setName("John");
      entity.setId(1);

      Student model = studentMapper.getModelFromEntity(entity);

      assertEquals(entity.getClassVal(), model.getClassName());
      assertEquals(entity.getName(), model.getName());
      assertEquals(entity.getId(), model.getId());
   }

   @Test
   public void testModelToEntity() {
      Student model = new Student();
      model.setId(1);
      model.setName("John");
      model.setClassName("X");

      StudentEntity entity = studentMapper.getEntityFromModel(model);

      assertEquals(entity.getClassVal(), model.getClassName());
      assertEquals(entity.getName(), model.getName());
      assertEquals(entity.getId(), model.getId());
   }
}

运行以下命令测试映射。

mvn clean test

命令成功后。验证输出。

mvn clean test
[INFO] Scanning for projects...
...
[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ mapping ---
[INFO] Surefire report directory: \mvn\mapping\target\surefire-reports

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running com.tutorialspoint.mapping.StudentMapperTest
Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.004 sec
...

MapStruct - 多对象映射

我们还可以添加映射多个对象的功能。例如,我们想使用 Student 和 Address 对象获取 DeliveryAddress 对象。

现在创建一个 Mapper 接口,它可以将两个对象映射到一个对象。

@Mapper
public interface DeliveryAddressMapper {
   @Mapping(source = "student.name", target = "name")
   @Mapping(source = "address.houseNo", target = "houseNumber")
   DeliveryAddress getDeliveryAddress(StudentEntity student, AddressEntity address);   
}

示例

在 Eclipse 中打开在 自定义映射 章节中更新的项目映射。

使用以下代码创建 DeliveryAddress.java -

DeliveryAddress.java

package com.tutorialspoint.model;

public class DeliveryAddress {	
	private String name;
	private int houseNumber;
	private String city;
	private String state;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getHouseNumber() {
		return houseNumber;
	}
	public void setHouseNumber(int houseNumber) {
		this.houseNumber = houseNumber;
	}
	public String getCity() {
		return city;
	}
	public void setCity(String city) {
		this.city = city;
	}
	public String getState() {
		return state;
	}
	public void setState(String state) {
		this.state = state;
	}
}

使用以下代码创建 AddressEntity.java -

AddressEntity.java

package com.tutorialspoint.entity;

public class AddressEntity {
	private int houseNo;
	private String city;
	private String state;
	public int getHouseNo() {
		return houseNo;
	}
	public void setHouseNo(int houseNo) {
		this.houseNo = houseNo;
	}
	public String getCity() {
		return city;
	}
	public void setCity(String city) {
		this.city = city;
	}
	public String getState() {
		return state;
	}
	public void setState(String state) {
		this.state = state;
	}
}

使用以下代码创建 DeliveryAddressMapper.java -

DeliveryAddressMapper.java

package com.tutorialspoint.mapper;

import org.mapstruct.Mapper;
import org.mapstruct.Mapping;

import com.tutorialspoint.entity.AddressEntity;
import com.tutorialspoint.entity.StudentEntity;
import com.tutorialspoint.model.DeliveryAddress;

@Mapper
public interface DeliveryAddressMapper {
   @Mapping(source = "student.name", target = "name")
   @Mapping(source = "address.houseNo", target = "houseNumber")
   DeliveryAddress getDeliveryAddress(StudentEntity student, AddressEntity address);   
}

使用以下代码创建 DeliveryAddressMapperTest.java -

DeliveryAddressMapperTest.java

package com.tutorialspoint.mapping;

import static org.junit.jupiter.api.Assertions.assertEquals;

import org.junit.jupiter.api.Test;
import org.mapstruct.factory.Mappers;

import com.tutorialspoint.entity.AddressEntity;
import com.tutorialspoint.entity.StudentEntity;
import com.tutorialspoint.mapper.DeliveryAddressMapper;
import com.tutorialspoint.model.DeliveryAddress;

public class DeliveryAddressMapperTest {

   private DeliveryAddressMapper deliveryAddressMapper
      = Mappers.getMapper(DeliveryAddressMapper.class);

   @Test
   public void testEntityToModel() {
      StudentEntity student = new StudentEntity();
      student.setClassVal("X");
      student.setName("John");
      student.setId(1);

      AddressEntity address = new AddressEntity();
      address.setCity("Y");
      address.setState("Z");
      address.setHouseNo(1);

      DeliveryAddress deliveryAddress = deliveryAddressMapper.getDeliveryAddress(student, address);

      assertEquals(deliveryAddress.getName(), student.getName());
      assertEquals(deliveryAddress.getCity(), address.getCity());
      assertEquals(deliveryAddress.getState(), address.getState());
      assertEquals(deliveryAddress.getHouseNumber(), address.getHouseNo());

   }
}	

运行以下命令测试映射。

mvn clean test

命令成功后。验证输出。

mvn clean test
[INFO] Scanning for projects...
...
[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ mapping ---
[INFO] Surefire report directory: \mvn\mapping\target\surefire-reports

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running com.tutorialspoint.mapping.DeliveryAddressMapperTest
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.011 sec
Running com.tutorialspoint.mapping.StudentMapperTest
Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.001 sec

Results :

Tests run: 3, Failures: 0, Errors: 0, Skipped: 0
...

MapStruct - 嵌套 Bean 映射

MapStruct 无缝处理嵌套映射。例如,具有 Subject 作为嵌套 Bean 的 Student。

现在创建一个 Mapper 接口,它可以映射嵌套对象。

@Mapper
public interface StudentMapper {
   @Mapping(target="className", source="classVal")
   @Mapping(target="subject", source="subject.name")
   Student getModelFromEntity(StudentEntity studentEntity);
	
   @Mapping(target="classVal", source="className")
   @Mapping(target="subject.name", source="subject")
   StudentEntity getEntityFromModel(Student student);
}

示例

在 Eclipse 中打开在 多对象映射 章节中更新的项目映射。

使用以下代码创建 SubjectEntity.java -

SubjectEntity.java

package com.tutorialspoint.entity;

public class SubjectEntity {
   private String name;
   public String getName() {
      return name;
   }

   public void setName(String name) {
      this.name = name;
   }	
}

使用以下代码更新 StudentEntity.java -

StudentEntity.java

package com.tutorialspoint.entity;

public class StudentEntity {
   private int id;
   private String name;
   private String classVal;
   private SubjectEntity subject;
   public int getId() {
      return id;
   }
   public void setId(int id) {
      this.id = id;
   }
   public String getName() {
      return name;
   }
   public void setName(String name) {
      this.name = name;
   }
   public String getClassVal() {
      return classVal;
   }
   public void setClassVal(String classVal) {
      this.classVal = classVal;
   }
   public SubjectEntity getSubject() {
      return subject;
   }
   public void setSubject(SubjectEntity subject) {
      this.subject = subject;
   }
}

使用以下代码更新 Student.java -

Student.java

package com.tutorialspoint.model;

public class Student {
   private int id;
   private String name;
   private String className;
   private String subject;
   public int getId() {
      return id;
   }
   public void setId(int id) {
      this.id = id;
   }
   public String getName() {
      return name;
   }
   public void setName(String name) {
      this.name = name;
   }
   public String getClassName() {
      return className;
   }
   public void setClassName(String className) {
      this.className = className;
   }
   public String getSubject() {
      return subject;
   }
   public void setSubject(String subject) {
      this.subject = subject;
   }
}

使用以下代码更新 StudentMapper.java -

StudentMapper.java

package com.tutorialspoint.mapper;

import org.mapstruct.Mapper;
import org.mapstruct.Mapping;

import com.tutorialspoint.entity.StudentEntity;
import com.tutorialspoint.model.Student;

@Mapper
public interface StudentMapper {

   @Mapping(target="className", source="classVal")
   @Mapping(target="subject", source="subject.name")
   Student getModelFromEntity(StudentEntity studentEntity);

   @Mapping(target="classVal", source="className")
   @Mapping(target="subject.name", source="subject")
   StudentEntity getEntityFromModel(Student student);
}

使用以下代码更新 StudentMapperTest.java -

StudentMapperTest.java

package com.tutorialspoint.mapping;

import static org.junit.jupiter.api.Assertions.assertEquals;

import org.junit.jupiter.api.Test;
import org.mapstruct.factory.Mappers;

import com.tutorialspoint.entity.StudentEntity;
import com.tutorialspoint.entity.SubjectEntity;
import com.tutorialspoint.mapper.StudentMapper;
import com.tutorialspoint.model.Student;

public class StudentMapperTest {
   private StudentMapper studentMapper
      = Mappers.getMapper(StudentMapper.class);

   @Test
   public void testEntityToModel() {
      StudentEntity entity = new StudentEntity();
      entity.setClassVal("X");
      entity.setName("John");
      entity.setId(1);

      SubjectEntity subject = new SubjectEntity();
      subject.setName("Computer");
      entity.setSubject(subject);

      Student model = studentMapper.getModelFromEntity(entity);

      assertEquals(entity.getClassVal(), model.getClassName());
      assertEquals(entity.getName(), model.getName());
      assertEquals(entity.getId(), model.getId());
      assertEquals(entity.getSubject().getName(), model.getSubject());        
   }

   @Test
   public void testModelToEntity() {
      Student model = new Student();
      model.setId(1);
      model.setName("John");
      model.setClassName("X");
      model.setSubject("Science");
      StudentEntity entity = studentMapper.getEntityFromModel(model);

      assertEquals(entity.getClassVal(), model.getClassName());
      assertEquals(entity.getName(), model.getName());
      assertEquals(entity.getId(), model.getId());
      assertEquals(entity.getSubject().getName(), model.getSubject());
   }
}

运行以下命令测试映射。

mvn clean test

命令成功后。验证输出。

mvn clean test
[INFO] Scanning for projects...
...
[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ mapping ---
[INFO] Surefire report directory: \mvn\mapping\target\surefire-reports

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running com.tutorialspoint.mapping.DeliveryAddressMapperTest
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.005 sec
Running com.tutorialspoint.mapping.StudentMapperTest
Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.002 sec

Results :

Tests run: 3, Failures: 0, Errors: 0, Skipped: 0
...

MapStruct - 直接字段映射

MapStruct 轻松处理直接字段映射。例如,Student 具有 section 作为私有属性,而 StudentEntity 具有 section 作为公共属性。要进行 getter/setter 映射,属性必须是公共的。如果是 public final,则只有 getter 方法可用于映射。

现在创建一个 Mapper 接口。我们将使用 @InheritInverseConfiguration 注解来复制反向配置。

@Mapper
public interface StudentMapper {
   @Mapping(target="className", source="classVal")
   @Mapping(target="subject", source="subject.name")
   Student getModelFromEntity(StudentEntity studentEntity);
	
   @InheritInverseConfiguration
   StudentEntity getEntityFromModel(Student student);
}

示例

在 Eclipse 中打开在 嵌套对象映射 章节中更新的项目映射。

使用以下代码更新 StudentEntity.java -

StudentEntity.java

package com.tutorialspoint.entity;

public class StudentEntity {
   private int id;
   private String name;
   private String classVal;
   private SubjectEntity subject;
   public String section;
   public int getId() {
      return id;
   }
   public void setId(int id) {
      this.id = id;
   }
   public String getName() {
      return name;
   }
   public void setName(String name) {
      this.name = name;
   }
   public String getClassVal() {
      return classVal;
   }
   public void setClassVal(String classVal) {
      this.classVal = classVal;
   }
   public SubjectEntity getSubject() {
      return subject;
   }
   public void setSubject(SubjectEntity subject) {
      this.subject = subject;
   }
}

使用以下代码更新 Student.java -

Student.java

package com.tutorialspoint.model;

public class Student {
   private int id;
   private String name;
   private String className;
   private String subject;
   private String section;
   public int getId() {
      return id;
   }
   public void setId(int id) {
      this.id = id;
   }
   public String getName() {
      return name;
   }
   public void setName(String name) {
      this.name = name;
   }
   public String getClassName() {
      return className;
   }
   public void setClassName(String className) {
      this.className = className;
   }
   public String getSubject() {
      return subject;
   }
   public void setSubject(String subject) {
      this.subject = subject;
   }
   public String getSection() {
      return section;
   }
   public void setSection(String section) {
      this.section = section;
   }
}

使用以下代码更新 StudentMapper.java -

StudentMapper.java

package com.tutorialspoint.mapper;

import org.mapstruct.InheritInverseConfiguration;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;

import com.tutorialspoint.entity.StudentEntity;
import com.tutorialspoint.model.Student;

@Mapper
public interface StudentMapper {

   @Mapping(target="className", source="classVal")
   @Mapping(target="subject", source="subject.name")
   Student getModelFromEntity(StudentEntity studentEntity);

   @InheritInverseConfiguration
   StudentEntity getEntityFromModel(Student student);
}

使用以下代码更新 StudentMapperTest.java -

StudentMapperTest.java

package com.tutorialspoint.mapping;

import static org.junit.jupiter.api.Assertions.assertEquals;

import org.junit.jupiter.api.Test;
import org.mapstruct.factory.Mappers;

import com.tutorialspoint.entity.StudentEntity;
import com.tutorialspoint.entity.SubjectEntity;
import com.tutorialspoint.mapper.StudentMapper;
import com.tutorialspoint.model.Student;

public class StudentMapperTest {
   private StudentMapper studentMapper
      = Mappers.getMapper(StudentMapper.class);

   @Test
   public void testEntityToModel() {
      StudentEntity entity = new StudentEntity();
      entity.setClassVal("X");
      entity.setName("John");
      entity.setId(1);
      entity.section = "A";
      SubjectEntity subject = new SubjectEntity();
      subject.setName("Computer");
      entity.setSubject(subject);

      Student model = studentMapper.getModelFromEntity(entity);

      assertEquals(entity.getClassVal(), model.getClassName());
      assertEquals(entity.getName(), model.getName());
      assertEquals(entity.getId(), model.getId());
      assertEquals(entity.getSubject().getName(), model.getSubject());
      assertEquals(entity.section, model.getSection());	  
   }

   @Test
   public void testModelToEntity() {
      Student model = new Student();
      model.setId(1);
      model.setName("John");
      model.setClassName("X");
      model.setSubject("Science");
      model.setSection("A");
      StudentEntity entity = studentMapper.getEntityFromModel(model);

      assertEquals(entity.getClassVal(), model.getClassName());
      assertEquals(entity.getName(), model.getName());
      assertEquals(entity.getId(), model.getId());
      assertEquals(entity.getSubject().getName(), model.getSubject());
      assertEquals(entity.section, model.getSection());
   }
}

运行以下命令测试映射。

mvn clean test

命令成功后。验证输出。

mvn clean test
[INFO] Scanning for projects...
...
[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ mapping ---
[INFO] Surefire report directory: \mvn\mapping\target\surefire-reports

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running com.tutorialspoint.mapping.DeliveryAddressMapperTest
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.005 sec
Running com.tutorialspoint.mapping.StudentMapperTest
Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.002 sec

Results :

Tests run: 3, Failures: 0, Errors: 0, Skipped: 0
...

MapStruct - 使用 Builder

MapStruct 允许使用 Builder。我们可以使用 Builder 框架或使用我们自定义的 Builder。在下面的示例中,我们使用自定义 Builder。

示例

在 Eclipse 中打开在 直接字段映射 章节中更新的项目映射。

使用以下代码更新 Student.java -

Student.java

package com.tutorialspoint.model;

public class Student {
   private final String name;
   private final int id;

   protected Student(Student.Builder builder) {
      this.name = builder.name;
      this.id = builder.id;
   }
   public static Student.Builder builder() {
      return new Student.Builder();
   }
   public static class Builder {
      private String name;
      private int id;
      public Builder name(String name) {
         this.name = name;
         return this;
      }
      public Builder id(int id) {
         this.id = id;
         return this;
      }
      public Student create() {
         return new Student( this );
      }
   }
   public String getName() {
      return name;
   }
   public int getId() {
      return id;
   }
}

使用以下代码更新 StudentMapper.java -

StudentMapper.java

package com.tutorialspoint.mapper;

import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import com.tutorialspoint.entity.StudentEntity;
import com.tutorialspoint.model.Student;

@Mapper
public interface StudentMapper {
   Student getModelFromEntity(StudentEntity studentEntity);
   @Mapping(target="id", source="id")
   @Mapping(target="name", source="name")
   StudentEntity getEntityFromModel(Student student);
}

使用以下代码更新 StudentMapperTest.java -

StudentMapperTest.java

package com.tutorialspoint.mapping;

import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.Test;
import org.mapstruct.factory.Mappers;
import com.tutorialspoint.entity.StudentEntity;
import com.tutorialspoint.entity.SubjectEntity;
import com.tutorialspoint.mapper.StudentMapper;
import com.tutorialspoint.model.Student;

public class StudentMapperTest {
   private StudentMapper studentMapper = Mappers.getMapper(StudentMapper.class);
   
   @Test
   public void testEntityToModel() {
      StudentEntity entity = new StudentEntity();
      entity.setName("John");
      entity.setId(1);
      Student model = studentMapper.getModelFromEntity(entity);
      assertEquals(entity.getName(), model.getName());
      assertEquals(entity.getId(), model.getId());
   }
   @Test
   public void testModelToEntity() {
      Student.Builder builder = Student.builder().id(1).name("John");
      Student model = builder.create();
      StudentEntity entity = studentMapper.getEntityFromModel(model);
      assertEquals(entity.getName(), model.getName());
      assertEquals(entity.getId(), model.getId());
   }
}

运行以下命令测试映射。

mvn clean test

输出

命令成功后。验证输出。

mvn clean test
[INFO] Scanning for projects...
...
[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ mapping ---
[INFO] Surefire report directory: \mvn\mapping\target\surefire-reports

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running com.tutorialspoint.mapping.DeliveryAddressMapperTest
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.005 sec
Running com.tutorialspoint.mapping.StudentMapperTest
Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.002 sec

Results :

Tests run: 3, Failures: 0, Errors: 0, Skipped: 0
...

MapStruct - 隐式类型转换

MapStruct 在大多数情况下自动处理类型转换。例如,int 到 Long 或 String 的转换。转换也处理空值。以下是一些重要的自动转换。

  • 在基本类型和对应的包装类之间。

  • 在基本类型和 String 之间。

  • 在枚举类型和 String 之间。

  • 在 BigInt、BigDecimal 和 String 之间。

  • 在 Calendar/Date 和 XMLGregorianCalendar 之间。

  • 在 XMLGregorianCalendar 和 String 之间。

  • 在 Jodas 日期类型和 String 之间。

示例

在 Eclipse 中打开在 使用 Builder 映射 章节中更新的项目映射。

使用以下代码更新 StudentEntity.java -

StudentEntity.java

package com.tutorialspoint.entity;

public class StudentEntity {
   private String id;
   private String name;
   private String classVal;
   private SubjectEntity subject;
   public String section;
   public String getId() {
      return id;
   }
   public void setId(String id) {
      this.id = id;
   }
   public String getName() {
      return name;
   }
   public void setName(String name) {
      this.name = name;
   }
   public String getClassVal() {
      return classVal;
   }
   public void setClassVal(String classVal) {
      this.classVal = classVal;
   }
   public SubjectEntity getSubject() {
      return subject;
   }
   public void setSubject(SubjectEntity subject) {
      this.subject = subject;
   }
}

Student.java 保持不变,代码如下 -

Student.java

package com.tutorialspoint.model;

public class Student {
   private final String name;
   private final int id;

   protected Student(Student.Builder builder) {
      this.name = builder.name;
      this.id = builder.id;
   }

   public static Student.Builder builder() {
      return new Student.Builder();
   }

   public static class Builder {
      private String name;
      private int id;

      public Builder name(String name) {
         this.name = name;
         return this;
      }

      public Builder id(int id) {
         this.id = id;
         return this;
      }

      public Student create() {
         return new Student( this );
      }
   }

   public String getName() {
      return name;
   }

   public int getId() {
      ret+urn id;
   }
}

使用以下代码更新 DeliveryAddressMapperTest.java -

DeliveryAddressMapperTest.java

package com.tutorialspoint.mapping;

import static org.junit.jupiter.api.Assertions.assertEquals;

import org.junit.jupiter.api.Test;
import org.mapstruct.factory.Mappers;

import com.tutorialspoint.entity.AddressEntity;
import com.tutorialspoint.entity.StudentEntity;
import com.tutorialspoint.mapper.DeliveryAddressMapper;
import com.tutorialspoint.model.DeliveryAddress;

public class DeliveryAddressMapperTest {

   private DeliveryAddressMapper deliveryAddressMapper
      = Mappers.getMapper(DeliveryAddressMapper.class);

   @Test
   public void testEntityToModel() {
      StudentEntity student = new StudentEntity();
      student.setClassVal("X");
      student.setName("John");
      student.setId("1");

      AddressEntity address = new AddressEntity();
      address.setCity("Y");
      address.setState("Z");
      address.setHouseNo(1);

      DeliveryAddress deliveryAddress = deliveryAddressMapper.getDeliveryAddress(student, address);

      assertEquals(deliveryAddress.getName(), student.getName());
      assertEquals(deliveryAddress.getCity(), address.getCity());
      assertEquals(deliveryAddress.getState(), address.getState());
      assertEquals(deliveryAddress.getHouseNumber(), address.getHouseNo());

   }
}

使用以下代码更新 StudentMapperTest.java -

StudentMapperTest.java

package com.tutorialspoint.mapping;

import static org.junit.jupiter.api.Assertions.assertEquals;

import org.junit.jupiter.api.Test;
import org.mapstruct.factory.Mappers;

import com.tutorialspoint.entity.StudentEntity;
import com.tutorialspoint.entity.SubjectEntity;
import com.tutorialspoint.mapper.StudentMapper;
import com.tutorialspoint.model.Student;

public class StudentMapperTest {

   private StudentMapper studentMapper
      = Mappers.getMapper(StudentMapper.class);

   @Test
   public void testEntityToModel() {
      StudentEntity entity = new StudentEntity();
      entity.setName("John");
      entity.setId("1");

      Student model = studentMapper.getModelFromEntity(entity);
      assertEquals(entity.getName(), model.getName());
      assertEquals(Integer.parseInt(entity.getId()), model.getId());
   }

   @Test
   public void testModelToEntity() {
      Student.Builder builder = Student.builder().id(1).name("John");
      Student model = builder.create();
      StudentEntity entity = studentMapper.getEntityFromModel(model);

      assertEquals(entity.getName(), model.getName());
      assertEquals(Integer.parseInt(entity.getId()), model.getId());
   }
}

运行以下命令测试映射。

mvn clean test

命令成功后。验证输出。

mvn clean test
[INFO] Scanning for projects...
...
[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ mapping ---
[INFO] Surefire report directory: \mvn\mapping\target\surefire-reports

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running com.tutorialspoint.mapping.DeliveryAddressMapperTest
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.005 sec
Running com.tutorialspoint.mapping.StudentMapperTest
Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.002 sec

Results :

Tests run: 3, Failures: 0, Errors: 0, Skipped: 0
...

MapStruct - 使用 numberFormat

MapStruct 无缝处理将数字转换为所需格式的 String。我们可以在 @Mapping 注解期间将所需的格式作为 numberFormat 传递。例如,考虑一种情况,其中以数字存储的金额需要以货币格式显示。

  • **源** - 实体的价格为 350。

  • **目标** - 模型显示价格为 $350.00。

  • **numberFormat** - 使用格式 $#.00

示例

在 Eclipse 中打开在 映射隐式类型转换 章节中更新的项目映射。

使用以下代码创建 CarEntity.java -

CarEntity.java

package com.tutorialspoint.entity;

public class CarEntity {
   private int id;
   private double price;
   public int getId() {
      return id;
   }
   public void setId(int id) {
      this.id = id;
   }
   public double getPrice() {
      return price;
   }
   public void setPrice(double price) {
      this.price = price;
   }
}

使用以下代码创建 Car.java -

Car.java

package com.tutorialspoint.model;

public class Car {
   private int id;
   private String price;
   public int getId() {
      return id;
   }
   public void setId(int id) {
      this.id = id;
   }
   public String getPrice() {
      return price;
   }
   public void setPrice(String price) {
      this.price = price;
   }
}

使用以下代码创建 CarMapper.java -

CarMapper.java

package com.tutorialspoint.mapper;

import org.mapstruct.Mapper;
import org.mapstruct.Mapping;

import com.tutorialspoint.entity.CarEntity;
import com.tutorialspoint.model.Car;

@Mapper
public interface CarMapper {
   @Mapping(source = "price", target = "price", numberFormat = "$#.00")
   Car getModelFromEntity(CarEntity carEntity);
}

使用以下代码创建 CarMapperTest.java -

CarMapperTest.java

package com.tutorialspoint.mapping;

import static org.junit.jupiter.api.Assertions.assertEquals;

import org.junit.jupiter.api.Test;
import org.mapstruct.factory.Mappers;

import com.tutorialspoint.entity.CarEntity;
import com.tutorialspoint.mapper.CarMapper;
import com.tutorialspoint.model.Car;

public class CarMapperTest {
   private CarMapper carMapper
      = Mappers.getMapper(CarMapper.class);

   @Test
   public void testEntityToModel() {
      CarEntity entity = new CarEntity();
      entity.setPrice(345000);
      entity.setId(1);

      Car model = carMapper.getModelFromEntity(entity);
      assertEquals(model.getPrice(), "$345000.00");
      assertEquals(entity.getId(), model.getId());
   }
}

运行以下命令测试映射。

mvn clean test

命令成功后。验证输出。

mvn clean test
[INFO] Scanning for projects...
...
[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ mapping ---
[INFO] Surefire report directory: \mvn\mapping\target\surefire-reports

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running com.tutorialspoint.mapping.CarMapperTest
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.035 sec
Running com.tutorialspoint.mapping.DeliveryAddressMapperTest
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0 sec
Running com.tutorialspoint.mapping.StudentMapperTest
Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.001 sec

Results :

Tests run: 4, Failures: 0, Errors: 0, Skipped: 0
...

MapStruct - 使用 dateFormat

MapStruct 无缝处理将日期转换为所需格式的 String。我们可以在 @Mapping 注解期间将所需的格式作为 dateFormat 传递。例如,考虑一种情况,其中以数字存储的日期需要以特定格式显示。

  • **源** - 实体的日期为 GregorianCalendar(2015, 3, 5)。

  • **目标** - 模型显示日期为 05.04.2015。

  • **dateFormat** - 使用格式 dd.MM.yyyy

示例

在 Eclipse 中打开项目映射,该映射在使用 numberFormat 映射章节中进行了更新。

使用以下代码更新 CarEntity.java −

CarEntity.java

package com.tutorialspoint.entity;
import java.util.GregorianCalendar;

public class CarEntity {
   private int id;
   private double price;
   private GregorianCalendar manufacturingDate;
   public int getId() {
      return id;
   }
   public void setId(int id) {
      this.id = id;
   }
   public double getPrice() {
      return price;
   }
   public void setPrice(double price) {
      this.price = price;
   }
   public GregorianCalendar getManufacturingDate() {
      return manufacturingDate;
   }
   public void setManufacturingDate(GregorianCalendar manufacturingDate) {
      this.manufacturingDate = manufacturingDate;
   }
}

使用以下代码更新 Car.java −

Car.java

package com.tutorialspoint.model;

public class Car {
   private int id;
   private String price;
   private String manufacturingDate;
   public int getId() {
      return id;
   }
   public void setId(int id) {
      this.id = id;
   }
   public String getPrice() {
      return price;
   }
   public void setPrice(String price) {
      this.price = price;
   }
   public String getManufacturingDate() {
      return manufacturingDate;
   }
   public void setManufacturingDate(String manufacturingDate) {
      this.manufacturingDate = manufacturingDate;
   }
}

使用以下代码更新 CarMapper.java −

CarMapper.java

package com.tutorialspoint.mapper;

import org.mapstruct.Mapper;
import org.mapstruct.Mapping;

import com.tutorialspoint.entity.CarEntity;
import com.tutorialspoint.model.Car;

@Mapper
public interface CarMapper {
   @Mapping(source = "price", target = "price", numberFormat = "$#.00")
   @Mapping(source = "manufacturingDate", target = "manufacturingDate", dateFormat = "dd.MM.yyyy")
   Car getModelFromEntity(CarEntity carEntity);
}

使用以下代码更新 CarMapperTest.java −

CarMapperTest.java

package com.tutorialspoint.mapping;

import static org.junit.jupiter.api.Assertions.assertEquals;
import java.util.GregorianCalendar;
import org.junit.jupiter.api.Test;
import org.mapstruct.factory.Mappers;

import com.tutorialspoint.entity.CarEntity;
import com.tutorialspoint.mapper.CarMapper;
import com.tutorialspoint.model.Car;

public class CarMapperTest {
   private CarMapper carMapper
      = Mappers.getMapper(CarMapper.class);

   @Test
   public void testEntityToModel() {
      CarEntity entity = new CarEntity();
      entity.setPrice(345000);
      entity.setId(1);
      entity.setManufacturingDate(new GregorianCalendar(2015, 3, 5));
      Car model = carMapper.getModelFromEntity(entity);
      assertEquals(model.getPrice(), "$345000.00");
      assertEquals(entity.getId(), model.getId());
      assertEquals("05.04.2015", model.getManufacturingDate());
   }
}

运行以下命令测试映射。

mvn clean test

命令成功后。验证输出。

mvn clean test
[INFO] Scanning for projects...
...
[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ mapping ---
[INFO] Surefire report directory: \mvn\mapping\target\surefire-reports

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running com.tutorialspoint.mapping.CarMapperTest
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.035 sec
Running com.tutorialspoint.mapping.DeliveryAddressMapperTest
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0 sec
Running com.tutorialspoint.mapping.StudentMapperTest
Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.001 sec

Results :

Tests run: 4, Failures: 0, Errors: 0, Skipped: 0
...

MapStruct - 使用表达式

MapStruct 允许为自定义逻辑调用转换方法。我们可以使用表达式来实现相同的功能,在表达式中我们可以传递任何 Java 对象并调用其方法进行转换。

语法

@Mapping(target = "target-property", 
	expression = "java(target-method())")

这里

  • 目标属性 - 我们正在进行映射的属性。

  • 表达式 - 映射器将调用表达式中编写的 Java 方法。

  • 目标方法 - 目标方法是要调用的方法。如果方法存在于不同的类中,请使用 new 类名.目标方法()

示例

在 Eclipse 中打开项目映射,该映射在使用 dateFormat 映射章节中进行了更新。

使用以下代码更新 CarEntity.java −

CarEntity.java

package com.tutorialspoint.entity;
import java.util.GregorianCalendar;

public class CarEntity {
   private int id;
   private double price;
   private GregorianCalendar manufacturingDate;
   public int getId() {
      return id;
   }
   public void setId(int id) {
      this.id = id;
   }
   public double getPrice() {
      return price;
   }
   public void setPrice(double price) {
      this.price = price;
   }
   public GregorianCalendar getManufacturingDate() {
      return manufacturingDate;
   }
   public void setManufacturingDate(GregorianCalendar manufacturingDate) {
      this.manufacturingDate = manufacturingDate;
   }
}

使用以下代码更新 Car.java −

Car.java

package com.tutorialspoint.model;

public class Car {
   private int id;
   private String price;
   private String manufacturingDate;
   public int getId() {
      return id;
   }
   public void setId(int id) {
      this.id = id;
   }
   public String getPrice() {
      return price;
   }
   public void setPrice(String price) {
      this.price = price;
   }
   public String getManufacturingDate() {
      return manufacturingDate;
   }
   public void setManufacturingDate(String manufacturingDate) {
      this.manufacturingDate = manufacturingDate;
   }
}

使用以下代码更新 CarMapper.java −

CarMapper.java

package com.tutorialspoint.mapper;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.GregorianCalendar;

import org.mapstruct.Mapper;
import org.mapstruct.Mapping;

import com.tutorialspoint.entity.CarEntity;
import com.tutorialspoint.model.Car;

@Mapper
public interface CarMapper {
   @Mapping(source = "price", target = "price", numberFormat = "$#.00")
   @Mapping(target = "manufacturingDate", 
      expression = "java(getManufacturingDate(carEntity.getManufacturingDate()))")
   Car getModelFromEntity(CarEntity carEntity);

   default String getManufacturingDate(GregorianCalendar manufacturingDate) {
      Date d = manufacturingDate.getTime();
      SimpleDateFormat sdf = new SimpleDateFormat( "dd.MM.yyyy" );
      return sdf.format( d );
   }
}

使用以下代码更新 CarMapperTest.java −

CarMapperTest.java

package com.tutorialspoint.mapping;

import static org.junit.jupiter.api.Assertions.assertEquals;
import java.util.GregorianCalendar;
import org.junit.jupiter.api.Test;
import org.mapstruct.factory.Mappers;

import com.tutorialspoint.entity.CarEntity;
import com.tutorialspoint.mapper.CarMapper;
import com.tutorialspoint.model.Car;

public class CarMapperTest {
   private CarMapper carMapper
      = Mappers.getMapper(CarMapper.class);

   @Test
   public void testEntityToModel() {
      CarEntity entity = new CarEntity();
      entity.setPrice(345000);
      entity.setId(1);
      entity.setManufacturingDate(new GregorianCalendar(2015, 3, 5));
      Car model = carMapper.getModelFromEntity(entity);
      assertEquals(model.getPrice(), "$345000.00");
      assertEquals(entity.getId(), model.getId());
      assertEquals("05.04.2015", model.getManufacturingDate());
   }
}

运行以下命令测试映射。

mvn clean test

命令成功后。验证输出。

mvn clean test
[INFO] Scanning for projects...
...
[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ mapping ---
[INFO] Surefire report directory: \mvn\mapping\target\surefire-reports

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running com.tutorialspoint.mapping.CarMapperTest
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.035 sec
Running com.tutorialspoint.mapping.DeliveryAddressMapperTest
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0 sec
Running com.tutorialspoint.mapping.StudentMapperTest
Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.001 sec

Results :

Tests run: 4, Failures: 0, Errors: 0, Skipped: 0
...

MapStruct - 使用常量

MapStruct 允许将常量值映射到属性。

语法

@Mapping(target = "target-property", const = "const-value")

这里

  • 目标属性 - 我们正在进行映射的属性。

  • 常量值 - 映射器将常量值映射到目标属性。

以下示例演示了相同的功能。

示例

在 Eclipse 中打开项目映射,该映射在使用 dateFormat 映射章节中进行了更新。

使用以下代码更新 CarEntity.java −

CarEntity.java

package com.tutorialspoint.entity;
import java.util.GregorianCalendar;

public class CarEntity {
   private int id;
   private double price;
   private GregorianCalendar manufacturingDate;
   public int getId() {
      return id;
   }
   public void setId(int id) {
      this.id = id;
   }
   public double getPrice() {
      return price;
   }
   public void setPrice(double price) {
      this.price = price;
   }
   public GregorianCalendar getManufacturingDate() {
      return manufacturingDate;
   }
   public void setManufacturingDate(GregorianCalendar manufacturingDate) {
      this.manufacturingDate = manufacturingDate;
   }
}

使用以下代码更新 Car.java −

Car.java

package com.tutorialspoint.model;

public class Car {
   private int id;
   private String price;
   private String manufacturingDate;
   private String brand;
   public int getId() {
      return id;
   }
   public void setId(int id) {
      this.id = id;
   }
   public String getPrice() {
      return price;
   }
   public void setPrice(String price) {
      this.price = price;
   }
   public String getManufacturingDate() {
      return manufacturingDate;
   }
   public void setManufacturingDate(String manufacturingDate) {
      this.manufacturingDate = manufacturingDate;
   }
   public String getBrand() {
      return brand;
   }
   public void setBrand(String brand) {
      this.brand = brand;
   }
}

使用以下代码更新 CarMapper.java −

CarMapper.java

package com.tutorialspoint.mapper;

import org.mapstruct.Mapper;
import org.mapstruct.Mapping;

import com.tutorialspoint.entity.CarEntity;
import com.tutorialspoint.model.Car;

@Mapper
public interface CarMapper {
   @Mapping(target = "brand", constant = "BMW")
   @Mapping(source = "price", target = "price", numberFormat = "$#.00")
   @Mapping(source = "manufacturingDate", target = "manufacturingDate", dateFormat = "dd.MM.yyyy")
   Car getModelFromEntity(CarEntity carEntity);
}

使用以下代码更新 CarMapperTest.java −

CarMapperTest.java

package com.tutorialspoint.mapping;

import static org.junit.jupiter.api.Assertions.assertEquals;
import java.util.GregorianCalendar;
import org.junit.jupiter.api.Test;
import org.mapstruct.factory.Mappers;

import com.tutorialspoint.entity.CarEntity;
import com.tutorialspoint.mapper.CarMapper;
import com.tutorialspoint.model.Car;

public class CarMapperTest {
   private CarMapper carMapper
      = Mappers.getMapper(CarMapper.class);

   @Test
   public void testEntityToModel() {
      CarEntity entity = new CarEntity();
      entity.setPrice(345000);
      entity.setId(1);
      entity.setManufacturingDate(new GregorianCalendar(2015, 3, 5));
      Car model = carMapper.getModelFromEntity(entity);
      assertEquals(model.getPrice(), "$345000.00");
      assertEquals(entity.getId(), model.getId());
      assertEquals("05.04.2015", model.getManufacturingDate());
      assertEquals("BMW", model.getBrand());
   }
}

运行以下命令测试映射。

mvn clean test

命令成功后。验证输出。

mvn clean test
[INFO] Scanning for projects...
...
[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ mapping ---
[INFO] Surefire report directory: \mvn\mapping\target\surefire-reports

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running com.tutorialspoint.mapping.CarMapperTest
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.035 sec
Running com.tutorialspoint.mapping.DeliveryAddressMapperTest
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0 sec
Running com.tutorialspoint.mapping.StudentMapperTest
Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.001 sec

Results :

Tests run: 4, Failures: 0, Errors: 0, Skipped: 0
...

MapStruct - 使用 defaultValue

使用 Mapstruct,如果源属性为 null,我们可以使用 @Mapping 注解的 defaultValue 属性传递默认值。

语法

@Mapping(target = "target-property", source="source-property" 
defaultValue = "default-value")

这里

  • 默认值 - 如果源属性为 null,则目标属性将设置为默认值。

以下示例演示了相同的功能。

示例

在 Eclipse 中打开项目映射,该映射在使用 Constant 映射章节中进行了更新。

使用以下代码更新 CarEntity.java −

CarEntity.java

package com.tutorialspoint.entity;
import java.util.GregorianCalendar;

public class CarEntity {
   private int id;
   private double price;
   private GregorianCalendar manufacturingDate;
   private String name;
   public int getId() {
      return id;
   }
   public void setId(int id) {
      this.id = id;
   }
   public double getPrice() {
      return price;
   }
   public void setPrice(double price) {
      this.price = price;
   }
   public GregorianCalendar getManufacturingDate() {
      return manufacturingDate;
   }
   public void setManufacturingDate(GregorianCalendar manufacturingDate) {
      this.manufacturingDate = manufacturingDate;
   }
   public String getName() {
      return name;
   }
   public void setName(String name) {
      this.name = name;
   }
}

使用以下代码更新 Car.java −

Car.java

package com.tutorialspoint.model;

public class Car {
   private int id;
   private String price;
   private String manufacturingDate;
   private String brand;
   private String name;
   public int getId() {
      return id;
   }
   public void setId(int id) {
      this.id = id;
   }
   public String getPrice() {
      return price;
   }
   public void setPrice(String price) {
      this.price = price;
   }
   public String getManufacturingDate() {
      return manufacturingDate;
   }
   public void setManufacturingDate(String manufacturingDate) {
      this.manufacturingDate = manufacturingDate;
   }
   public String getBrand() {
      return brand;
   }
   public void setBrand(String brand) {
      this.brand = brand;
   }
   public String getName() {
      return name;
   }
   public void setName(String name) {
      this.name = name;
   }
}

使用以下代码更新 CarMapper.java −

CarMapper.java

package com.tutorialspoint.mapper;

import org.mapstruct.Mapper;
import org.mapstruct.Mapping;

import com.tutorialspoint.entity.CarEntity;
import com.tutorialspoint.model.Car;

@Mapper
public interface CarMapper {
   @Mapping(source = "name", target = "name", defaultValue = "Sample")
   @Mapping(target = "brand", constant = "BMW")
   @Mapping(source = "price", target = "price", numberFormat = "$#.00")
   @Mapping(source = "manufacturingDate", target = "manufacturingDate", dateFormat = "dd.MM.yyyy")
   Car getModelFromEntity(CarEntity carEntity);
}

使用以下代码更新 CarMapperTest.java −

CarMapperTest.java

package com.tutorialspoint.mapping;

import static org.junit.jupiter.api.Assertions.assertEquals;
import java.util.GregorianCalendar;
import org.junit.jupiter.api.Test;
import org.mapstruct.factory.Mappers;

import com.tutorialspoint.entity.CarEntity;
import com.tutorialspoint.mapper.CarMapper;
import com.tutorialspoint.model.Car;

public class CarMapperTest {
   private CarMapper carMapper
      = Mappers.getMapper(CarMapper.class);

   @Test
   public void testEntityToModel() {
      CarEntity entity = new CarEntity();
      entity.setPrice(345000);
      entity.setId(1);
      entity.setManufacturingDate(new GregorianCalendar(2015, 3, 5));
      Car model = carMapper.getModelFromEntity(entity);
      assertEquals(model.getPrice(), "$345000.00");
      assertEquals(entity.getId(), model.getId());
      assertEquals("05.04.2015", model.getManufacturingDate());
      assertEquals("Sample", model.getName());
      assertEquals("BMW", model.getBrand());
   }
}

运行以下命令测试映射。

mvn clean test

命令成功后。验证输出。

mvn clean test
[INFO] Scanning for projects...
...
[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ mapping ---
[INFO] Surefire report directory: \mvn\mapping\target\surefire-reports

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running com.tutorialspoint.mapping.CarMapperTest
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.035 sec
Running com.tutorialspoint.mapping.DeliveryAddressMapperTest
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0 sec
Running com.tutorialspoint.mapping.StudentMapperTest
Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.001 sec

Results :

Tests run: 4, Failures: 0, Errors: 0, Skipped: 0
...

MapStruct - 使用 defaultExpression

使用 Mapstruct,如果源属性为 null,我们可以使用 @Mapping 注解的 defaultExpression 属性传递计算值。

语法

@Mapping(target = "target-property", source="source-property" defaultExpression = "default-value-method")

这里

  • 默认值方法 - 如果源属性为 null,则目标属性将设置为默认值方法的结果。

以下示例演示了相同的功能。

示例

在 Eclipse 中打开项目映射,该映射在使用 defaultValue 映射章节中进行了更新。

使用以下代码更新 CarEntity.java −

CarEntity.java

package com.tutorialspoint.entity;
import java.util.GregorianCalendar;

public class CarEntity {
   private int id;
   private double price;
   private GregorianCalendar manufacturingDate;
   private String name;
   public int getId() {
      return id;
   }
   public void setId(int id) {
      this.id = id;
   }
   public double getPrice() {
      return price;
   }
   public void setPrice(double price) {
      this.price = price;
   }
   public GregorianCalendar getManufacturingDate() {
      return manufacturingDate;
   }
   public void setManufacturingDate(GregorianCalendar manufacturingDate) {
      this.manufacturingDate = manufacturingDate;
   }
   public String getName() {
      return name;
   }
   public void setName(String name) {
      this.name = name;
   }
}

使用以下代码更新 Car.java −

Car.java

package com.tutorialspoint.model;
public class Car {
   private int id;
   private String price;
   private String manufacturingDate;
   private String brand;
   private String name;
   public int getId() {
      return id;
   }
   public void setId(int id) {
      this.id = id;
   }
   public String getPrice() {
      return price;
   }
   public void setPrice(String price) {
      this.price = price;
   }
   public String getManufacturingDate() {
      return manufacturingDate;
   }
   public void setManufacturingDate(String manufacturingDate) {
      this.manufacturingDate = manufacturingDate;
   }
   public String getBrand() {
      return brand;
   }
   public void setBrand(String brand) {
      this.brand = brand;
   }
   public String getName() {
      return name;
   }
   public void setName(String name) {
      this.name = name;
   }
}

使用以下代码更新 CarMapper.java −

CarMapper.java

package com.tutorialspoint.mapper;

import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import com.tutorialspoint.entity.CarEntity;
import com.tutorialspoint.model.Car;
import java.util.UUID;

@Mapper( imports = UUID.class )
public interface CarMapper {
   @Mapping(source = "name", target = "name", defaultExpression = "java(UUID.randomUUID().toString())")
   @Mapping(target = "brand", constant = "BMW")
   @Mapping(source = "price", target = "price", numberFormat = "$#.00")
   @Mapping(source = "manufacturingDate", target = "manufacturingDate", dateFormat = "dd.MM.yyyy")
   Car getModelFromEntity(CarEntity carEntity);
}

使用以下代码更新 CarMapperTest.java −

CarMapperTest.java

package com.tutorialspoint.mapping;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import java.util.GregorianCalendar;
import org.junit.jupiter.api.Test;
import org.mapstruct.factory.Mappers;
import com.tutorialspoint.entity.CarEntity;
import com.tutorialspoint.mapper.CarMapper;
import com.tutorialspoint.model.Car;

public class CarMapperTest {
   private CarMapper carMapper=Mappers.getMapper(CarMapper.class);

   @Test
   public void testEntityToModel() {
      CarEntity entity = new CarEntity();
      entity.setPrice(345000);
      entity.setId(1);
      entity.setManufacturingDate(new GregorianCalendar(2015, 3, 5));
      Car model = carMapper.getModelFromEntity(entity);
      assertEquals(model.getPrice(), "$345000.00");
      assertEquals(entity.getId(), model.getId());
      assertEquals("05.04.2015", model.getManufacturingDate());
      assertNotNull(model.getName());
      assertEquals("BMW", model.getBrand());
   }
}

运行以下命令测试映射。

mvn clean test

输出

命令成功后。验证输出。

mvn clean test
[INFO] Scanning for projects...
...
[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ mapping ---
[INFO] Surefire report directory: \mvn\mapping\target\surefire-reports

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running com.tutorialspoint.mapping.CarMapperTest
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.035 sec
Running com.tutorialspoint.mapping.DeliveryAddressMapperTest
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0 sec
Running com.tutorialspoint.mapping.StudentMapperTest
Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.001 sec

Results :

Tests run: 4, Failures: 0, Errors: 0, Skipped: 0
...

MapStruct - 列表映射

使用 Mapstruct,我们可以像映射基本类型一样映射列表。要获取对象列表,我们应该提供一个可以映射对象的映射器方法。

语法

@Mapper
public interface CarMapper {
   List<String> getListOfStrings(List<Integer> listOfIntegers);
   List<Car> getCars(List<CarEntity> carEntities);
   Car getModelFromEntity(CarEntity carEntity);
}

以下示例演示了相同的功能。

示例

在 Eclipse 中打开项目映射,该映射在使用 defaultExpression 映射章节中进行了更新。

使用以下代码更新 CarEntity.java −

CarEntity.java

package com.tutorialspoint.entity;
import java.util.GregorianCalendar;

public class CarEntity {
   private int id;
   private double price;
   private GregorianCalendar manufacturingDate;
   private String name;
   public int getId() {
      return id;
   }
   public void setId(int id) {
      this.id = id;
   }
   public double getPrice() {
      return price;
   }
   public void setPrice(double price) {
      this.price = price;
   }
   public GregorianCalendar getManufacturingDate() {
      return manufacturingDate;
   }
   public void setManufacturingDate(GregorianCalendar manufacturingDate) {
      this.manufacturingDate = manufacturingDate;
   }
   public String getName() {
      return name;
   }
   public void setName(String name) {
      this.name = name;
   }
}

使用以下代码更新 Car.java −

Car.java

package com.tutorialspoint.model;

public class Car {
   private int id;
   private String price;
   private String manufacturingDate;
   private String brand;
   private String name;
   public int getId() {
      return id;
   }
   public void setId(int id) {
      this.id = id;
   }
   public String getPrice() {
      return price;
   }
   public void setPrice(String price) {
      this.price = price;
   }
   public String getManufacturingDate() {
      return manufacturingDate;
   }
   public void setManufacturingDate(String manufacturingDate) {
      this.manufacturingDate = manufacturingDate;
   }
   public String getBrand() {
      return brand;
   }
   public void setBrand(String brand) {
      this.brand = brand;
   }
   public String getName() {
      return name;
   }
   public void setName(String name) {
      this.name = name;
   }
}

使用以下代码更新 CarMapper.java −

CarMapper.java

package com.tutorialspoint.mapper;

import org.mapstruct.Mapper;
import org.mapstruct.Mapping;

import com.tutorialspoint.entity.CarEntity;
import com.tutorialspoint.model.Car;

import java.util.List;
import java.util.UUID;

@Mapper( imports = UUID.class )
public interface CarMapper {
   @Mapping(source = "name", target = "name", defaultExpression = "java(UUID.randomUUID().toString())")
   @Mapping(target = "brand", constant = "BMW")
   @Mapping(source = "price", target = "price", numberFormat = "$#.00")
   @Mapping(source = "manufacturingDate", target = "manufacturingDate", dateFormat = "dd.MM.yyyy")
   Car getModelFromEntity(CarEntity carEntity);

   List<String> getListOfStrings(List<Integer> listOfIntegers);
   List<Car> getCars(List<CarEntity> carEntities);
}

使用以下代码更新 CarMapperTest.java −

CarMapperTest.java

package com.tutorialspoint.mapping;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;

import java.util.Arrays;
import java.util.GregorianCalendar;
import java.util.List;

import org.junit.jupiter.api.Test;
import org.mapstruct.factory.Mappers;

import com.tutorialspoint.entity.CarEntity;
import com.tutorialspoint.mapper.CarMapper;
import com.tutorialspoint.model.Car;

public class CarMapperTest {
   private CarMapper carMapper
      = Mappers.getMapper(CarMapper.class);

   @Test
   public void testEntityToModel() {
      CarEntity entity = new CarEntity();
      entity.setPrice(345000);
      entity.setId(1);
      entity.setManufacturingDate(new GregorianCalendar(2015, 3, 5));

      CarEntity entity1 = new CarEntity();
      entity1.setPrice(445000);
      entity1.setId(2);
      entity1.setManufacturingDate(new GregorianCalendar(2015, 3, 5));

      List<CarEntity> carEntities = Arrays.asList(entity, entity1);

      Car model = carMapper.getModelFromEntity(entity);
      assertEquals("$345000.00",model.getPrice());
      assertEquals(entity.getId(), model.getId());

      assertEquals("BMW", model.getBrand());
      assertEquals("05.04.2015", model.getManufacturingDate());

      List<Integer> list = Arrays.asList(1,2,3);
      List<String> listOfStrings = carMapper.getListOfStrings(list);
      List<Car> listOfCars = carMapper.getCars(carEntities);

      assertEquals(3, listOfStrings.size());
      assertEquals(2, listOfCars.size());
   }
}

运行以下命令测试映射。

mvn clean test

命令成功后。验证输出。

mvn clean test
[INFO] Scanning for projects...
...
[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ mapping ---
[INFO] Surefire report directory: \mvn\mapping\target\surefire-reports

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running com.tutorialspoint.mapping.CarMapperTest
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.035 sec
Running com.tutorialspoint.mapping.DeliveryAddressMapperTest
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0 sec
Running com.tutorialspoint.mapping.StudentMapperTest
Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.001 sec

Results :

Tests run: 4, Failures: 0, Errors: 0, Skipped: 0
...

MapStruct - Map 映射

使用 Mapstruct,我们可以使用 @MapMapping 注解创建映射对象。其他映射规则与我们之前看到的相同。

语法

@Mapper
public interface UtilityMapper {
   @MapMapping(valueDateFormat = "dd.MM.yyyy")
   Map<String, String> getMap(Map<Long, GregorianCalendar> source);
}

以下示例演示了相同的功能。

示例

在 Eclipse 中打开项目映射,该映射在映射列表章节中进行了更新。

使用以下代码创建 UtilityMapper.java −

UtilityMapper.java

package com.tutorialspoint.mapper;

import java.util.GregorianCalendar;
import java.util.Map;

import org.mapstruct.MapMapping;
import org.mapstruct.Mapper;

@Mapper
public interface UtilityMapper {
   @MapMapping(valueDateFormat = "dd.MM.yyyy")
   Map<String, String> getMap(Map<Long, GregorianCalendar> source);
}

使用以下代码创建 UtilityMapperTest.java −

UtilityMapperTest.java

package com.tutorialspoint.mapping;

import static org.junit.jupiter.api.Assertions.assertEquals;

import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.Map;

import org.junit.jupiter.api.Test;
import org.mapstruct.factory.Mappers;

import com.tutorialspoint.mapper.UtilityMapper;

public class UtilityMapperTest {
   private UtilityMapper utilityMapper
      = Mappers.getMapper(UtilityMapper.class);

   @Test
   public void testMapMapping() {
      Map<Long, GregorianCalendar> source = new HashMap<>();
      source.put(1L, new GregorianCalendar(2015, 3, 5));

      Map<String, String> target = utilityMapper.getMap(source);
      assertEquals("05.04.2015", target.get("1"));		
   }
}

运行以下命令测试映射。

mvn clean test

命令成功后。验证输出。

mvn clean test
[INFO] Scanning for projects...
...
[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ mapping ---
[INFO] Surefire report directory: \mvn\mapping\target\surefire-reports

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running com.tutorialspoint.mapping.CarMapperTest
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.327 sec
Running com.tutorialspoint.mapping.DeliveryAddressMapperTest
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.001 sec
Running com.tutorialspoint.mapping.StudentMapperTest
Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.001 sec
Running com.tutorialspoint.mapping.UtilityMapperTest
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.001 sec

Results :

Tests run: 5, Failures: 0, Errors: 0, Skipped: 0
...

MapStruct - 映射流

使用 Mapstruct,我们可以像处理集合一样创建流的映射。

语法

@Mapper
public interface UtilityMapper {
   Stream<String> getStream(Stream<Integer> source);
}

以下示例演示了相同的功能。

示例

在 Eclipse 中打开项目映射,该映射在映射映射章节中进行了更新。

使用以下代码更新 UtilityMapper.java −

UtilityMapper.java

package com.tutorialspoint.mapper;

import java.util.GregorianCalendar;
import java.util.Map;
import java.util.stream.Stream;
import org.mapstruct.MapMapping;
import org.mapstruct.Mapper;

@Mapper
public interface UtilityMapper {
   @MapMapping(valueDateFormat = "dd.MM.yyyy")
   Map<String, String> getMap(Map<Long, GregorianCalendar> source);
   Stream<String> getStream(Stream<Integer> source);
}

使用以下代码更新 UtilityMapperTest.java −

UtilityMapperTest.java

package com.tutorialspoint.mapping;

import static org.junit.jupiter.api.Assertions.assertEquals;
import java.util.Arrays;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Stream;
import org.junit.jupiter.api.Test;
import org.mapstruct.factory.Mappers;
import com.tutorialspoint.mapper.UtilityMapper;

public class UtilityMapperTest {
   private UtilityMapper utilityMapper=Mappers.getMapper(UtilityMapper.class);
   
   @Test
   public void testMapMapping() {
      Map<Long, GregorianCalendar> source = new HashMap<>();
      source.put(1L, new GregorianCalendar(2015, 3, 5));

      Map<String, String> target = utilityMapper.getMap(source);
      assertEquals("05.04.2015", target.get("1"));		
   }
   @Test
   public void testGetStream() {
      Stream<Integer> numbers = Arrays.asList(1, 2, 3, 4).stream();

      Stream<String> strings = utilityMapper.getStream(numbers);
      assertEquals(4, strings.count());			
   }
}

运行以下命令测试映射。

mvn clean test

输出

命令成功后。验证输出。

mvn clean test
[INFO] Scanning for projects...
...
[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ mapping ---
[INFO] Surefire report directory: \mvn\mapping\target\surefire-reports

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running com.tutorialspoint.mapping.CarMapperTest
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.327 sec
Running com.tutorialspoint.mapping.DeliveryAddressMapperTest
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.001 sec
Running com.tutorialspoint.mapping.StudentMapperTest
Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.001 sec
Running com.tutorialspoint.mapping.UtilityMapperTest
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.001 sec

Results :

Tests run: 5, Failures: 0, Errors: 0, Skipped: 0
...

MapStruct - 枚举映射

Mapstruct 自动映射枚举。名称相同的枚举会自动映射。如果名称不同,我们可以使用 @ValueMapping 注解进行映射。

语法

@Mapper
public interface UtilityMapper {
   @ValueMapping(source = "EXTRA", target = "SPECIAL")
   PlacedOrderType getEnum(OrderType order);
}

以下示例演示了相同的功能。

示例

在 Eclipse 中打开项目映射,该映射在映射流章节中进行了更新。

使用以下代码创建 OrderType.java −

OrderType.java

package com.tutorialspoint.enums;
public enum OrderType {
   EXTRA, NORMAL, STANDARD
}

使用以下代码创建 PlacedOrderType.java −

PlacedOrderType.java

package com.tutorialspoint.enums;
public enum PlacedOrderType {
   SPECIAL, NORMAL, STANDARD
}

使用以下代码更新 UtilityMapper.java −

UtilityMapper.java

package com.tutorialspoint.mapper;

import java.util.GregorianCalendar;
import java.util.Map;
import java.util.stream.Stream;
import org.mapstruct.MapMapping;
import org.mapstruct.Mapper;
import org.mapstruct.ValueMapping;
import com.tutorialspoint.enums.OrderType;
import com.tutorialspoint.enums.PlacedOrderType;

@Mapper
public interface UtilityMapper {
   @MapMapping(valueDateFormat = "dd.MM.yyyy")
   Map<String, String> getMap(Map<Long, GregorianCalendar> source);
   Stream<String> getStream(Stream<Integer> source);
   
   @ValueMapping(source = "EXTRA", target = "SPECIAL")
   PlacedOrderType getEnum(OrderType order);
}

使用以下代码更新 UtilityMapperTest.java −

UtilityMapperTest.java

package com.tutorialspoint.mapping;

import static org.junit.jupiter.api.Assertions.assertEquals;
import java.util.Arrays;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Stream;
import org.junit.jupiter.api.Test;
import org.mapstruct.factory.Mappers;
import com.tutorialspoint.enums.OrderType;
import com.tutorialspoint.enums.PlacedOrderType;
import com.tutorialspoint.mapper.UtilityMapper;

public class UtilityMapperTest {
   private UtilityMapper utilityMapper=Mappers.getMapper(UtilityMapper.class);

   @Test
   public void testMapMapping() {
      Map<Long, GregorianCalendar> source = new HashMap<>();
      source.put(1L, new GregorianCalendar(2015, 3, 5));

      Map<String, String> target = utilityMapper.getMap(source);
      assertEquals("05.04.2015", target.get("1"));		
   }
   @Test
   public void testGetStream() {
      Stream<Integer> numbers = Arrays.asList(1, 2, 3, 4).stream();
      Stream<String> strings = utilityMapper.getStream(numbers);
      assertEquals(4, strings.count());			
   }   
   @Test
   public void testGetEnum() {
      PlacedOrderType placedOrderType = utilityMapper.getEnum(OrderType.EXTRA);
      PlacedOrderType placedOrderType1 = utilityMapper.getEnum(OrderType.NORMAL);
      PlacedOrderType placedOrderType2 = utilityMapper.getEnum(OrderType.STANDARD);
      assertEquals(PlacedOrderType.SPECIAL.name(), placedOrderType.name());
      assertEquals(PlacedOrderType.NORMAL.name(), placedOrderType1.name());
      assertEquals(PlacedOrderType.STANDARD.name(), placedOrderType2.name());
   }
}

运行以下命令测试映射。

mvn clean test

输出

命令成功后。验证输出。

mvn clean test
[INFO] Scanning for projects...
...
[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ mapping ---
[INFO] Surefire report directory: \mvn\mapping\target\surefire-reports

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running com.tutorialspoint.mapping.CarMapperTest
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.256 sec
Running com.tutorialspoint.mapping.DeliveryAddressMapperTest
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.001 sec
Running com.tutorialspoint.mapping.StudentMapperTest
Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0 sec
Running com.tutorialspoint.mapping.UtilityMapperTest
Tests run: 3, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0 sec

Results :

Tests run: 7, Failures: 0, Errors: 0, Skipped: 0
...

MapStruct - 抛出异常

Mapstruct 映射器允许抛出特定异常。考虑自定义映射方法的情况,如果数据无效,我们希望抛出自定义异常。

语法

@Mapper(uses=DateMapper.class)
public interface UtilityMapper {
    CarEntity getCarEntity(Car car) throws ParseException;
}

以下示例演示了相同的功能。

示例

在 Eclipse 中打开项目映射,该映射在映射枚举章节中进行了更新。

使用以下代码更新 UtilityMapper.java −

UtilityMapper.java

package com.tutorialspoint.mapper;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Map;
import java.util.stream.Stream;

import org.mapstruct.MapMapping;
import org.mapstruct.Mapper;
import org.mapstruct.ValueMapping;

import com.tutorialspoint.entity.CarEntity;
import com.tutorialspoint.enums.OrderType;
import com.tutorialspoint.enums.PlacedOrderType;
import com.tutorialspoint.model.Car;

@Mapper(uses=DateMapper.class)
public interface UtilityMapper {
   @MapMapping(valueDateFormat = "dd.MM.yyyy")
   Map<String, String> getMap(Map<Long, GregorianCalendar> source);

   Stream<String> getStream(Stream<Integer> source);

   @ValueMapping(source = "EXTRA", target = "SPECIAL")
   PlacedOrderType getEnum(OrderType order);

   CarEntity getCarEntity(Car car) throws ParseException;
}

class DateMapper {
   public String asString(GregorianCalendar date) {
      return date != null ? new SimpleDateFormat( "yyyy-MM-dd" )
         .format( date.getTime() ) : null;
   }

   public GregorianCalendar asDate(String date) throws ParseException {
      Date date1 = date != null ? new SimpleDateFormat( "yyyy-MM-dd" )
         .parse( date ) : null;
      if(date1 != null) {
         return new GregorianCalendar(date1.getYear(), date1.getMonth(),date1.getDay());
      }
      return null;        
   }
}

使用以下代码更新 UtilityMapperTest.java −

UtilityMapperTest.java

package com.tutorialspoint.mapping;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;

import java.text.ParseException;
import java.util.Arrays;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Stream;

import org.junit.jupiter.api.Test;
import org.mapstruct.factory.Mappers;

import com.tutorialspoint.entity.CarEntity;
import com.tutorialspoint.enums.OrderType;
import com.tutorialspoint.enums.PlacedOrderType;
import com.tutorialspoint.mapper.UtilityMapper;
import com.tutorialspoint.model.Car;

public class UtilityMapperTest {
   private UtilityMapper utilityMapper
      = Mappers.getMapper(UtilityMapper.class);

   @Test
   public void testMapMapping() {
      Map<Long, GregorianCalendar> source = new HashMap<>();
      source.put(1L, new GregorianCalendar(2015, 3, 5));

      Map<String, String> target = utilityMapper.getMap(source);
      assertEquals("2015-04-05", target.get("1"));		
   }

   @Test
   public void testGetStream() {
      Stream<Integer> numbers = Arrays.asList(1, 2, 3, 4).stream();

      Stream<String> strings = utilityMapper.getStream(numbers);
      assertEquals(4, strings.count());			
   }

   @Test
   public void testGetEnum() {
      PlacedOrderType placedOrderType = utilityMapper.getEnum(OrderType.EXTRA);
      PlacedOrderType placedOrderType1 = utilityMapper.getEnum(OrderType.NORMAL);
      PlacedOrderType placedOrderType2 = utilityMapper.getEnum(OrderType.STANDARD);
      assertEquals(PlacedOrderType.SPECIAL.name(), placedOrderType.name());
      assertEquals(PlacedOrderType.NORMAL.name(), placedOrderType1.name());
      assertEquals(PlacedOrderType.STANDARD.name(), placedOrderType2.name());
   }

   @Test
   public void testGetCar() {
      Car car = new Car();
      car.setId(1);
      car.setManufacturingDate("11/10/2020");
      boolean exceptionOccured = false;
      try {
         CarEntity carEntity = utilityMapper.getCarEntity(car);
      } catch (ParseException e) {
         exceptionOccured = true;
      }
      assertTrue(exceptionOccured);
   }
}

运行以下命令测试映射。

mvn clean test

命令成功后。验证输出。

mvn clean test
[INFO] Scanning for projects...
...
[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ mapping ---
[INFO] Surefire report directory: \mvn\mapping\target\surefire-reports

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running com.tutorialspoint.mapping.CarMapperTest
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.256 sec
Running com.tutorialspoint.mapping.DeliveryAddressMapperTest
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.001 sec
Running com.tutorialspoint.mapping.StudentMapperTest
Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0 sec
Running com.tutorialspoint.mapping.UtilityMapperTest
Tests run: 4, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0 sec

Results :

Tests run: 8, Failures: 0, Errors: 0, Skipped: 0
...

MapStruct - 使用自定义映射器

Mapstruct 映射器允许创建自定义映射器方法来映射对象。对于映射器接口,我们可以添加默认方法。

语法

@Mapper(uses=DateMapper.class)
public interface UtilityMapper {
   default Car getCar(CarEntity entity) {
      Car car = new Car();
      car.setId(entity.getId());
      car.setName(entity.getName());
      return car;
   }
}

以下示例演示了相同的功能。

示例

在 Eclipse 中打开项目映射,该映射在映射枚举章节中进行了更新。

使用以下代码更新 UtilityMapper.java −

UtilityMapper.java

package com.tutorialspoint.mapper;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Map;
import java.util.stream.Stream;

import org.mapstruct.MapMapping;
import org.mapstruct.Mapper;
import org.mapstruct.ValueMapping;

import com.tutorialspoint.entity.CarEntity;
import com.tutorialspoint.enums.OrderType;
import com.tutorialspoint.enums.PlacedOrderType;
import com.tutorialspoint.model.Car;

@Mapper(uses=DateMapper.class)
public interface UtilityMapper {
   @MapMapping(valueDateFormat = "dd.MM.yyyy")
   Map<String, String> getMap(Map<Long, GregorianCalendar> source);

   Stream<String> getStream(Stream<Integer> source);

   @ValueMapping(source = "EXTRA", target = "SPECIAL")
   PlacedOrderType getEnum(OrderType order);

   CarEntity getCarEntity(Car car) throws ParseException;
   
   default Car getCar(CarEntity entity) {
      Car car = new Car();
      car.setId(entity.getId());
      car.setName(entity.getName());
      return car;
   }
}

class DateMapper {
   public String asString(GregorianCalendar date) {
      return date != null ? new SimpleDateFormat( "yyyy-MM-dd" )
         .format( date.getTime() ) : null;
   }

   public GregorianCalendar asDate(String date) throws ParseException {
      Date date1 = date != null ? new SimpleDateFormat( "yyyy-MM-dd" )
         .parse( date ) : null;
      if(date1 != null) {
         return new GregorianCalendar(date1.getYear(), date1.getMonth(),date1.getDay());
      }
      return null;        
   }
}

使用以下代码更新 UtilityMapperTest.java −

UtilityMapperTest.java

package com.tutorialspoint.mapping;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;

import java.text.ParseException;
import java.util.Arrays;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Stream;

import org.junit.jupiter.api.Test;
import org.mapstruct.factory.Mappers;

import com.tutorialspoint.entity.CarEntity;
import com.tutorialspoint.enums.OrderType;
import com.tutorialspoint.enums.PlacedOrderType;
import com.tutorialspoint.mapper.UtilityMapper;
import com.tutorialspoint.model.Car;

public class UtilityMapperTest {
   private UtilityMapper utilityMapper
      = Mappers.getMapper(UtilityMapper.class);

   @Test
   public void testMapMapping() {
      Map<Long, GregorianCalendar> source = new HashMap<>();
      source.put(1L, new GregorianCalendar(2015, 3, 5));

      Map<String, String> target = utilityMapper.getMap(source);
      assertEquals("2015-04-05", target.get("1"));		
   }

   @Test
   public void testGetStream() {
      Stream<Integer> numbers = Arrays.asList(1, 2, 3, 4).stream();
      Stream<String> strings = utilityMapper.getStream(numbers);
      assertEquals(4, strings.count());			
   }

   @Test
   public void testGetEnum() {
      PlacedOrderType placedOrderType = utilityMapper.getEnum(OrderType.EXTRA);
      PlacedOrderType placedOrderType1 = utilityMapper.getEnum(OrderType.NORMAL);
      PlacedOrderType placedOrderType2 = utilityMapper.getEnum(OrderType.STANDARD);
      assertEquals(PlacedOrderType.SPECIAL.name(), placedOrderType.name());
      assertEquals(PlacedOrderType.NORMAL.name(), placedOrderType1.name());
      assertEquals(PlacedOrderType.STANDARD.name(), placedOrderType2.name());
   }

   @Test
   public void testGetCarEntity() {
      Car car = new Car();
      car.setId(1);
      car.setManufacturingDate("11/10/2020");
      boolean exceptionOccured = false;
      try {
         CarEntity carEntity = utilityMapper.getCarEntity(car);
      } catch (ParseException e) {
         exceptionOccured = true;
      }
      assertTrue(exceptionOccured);
   }

   @Test
   public void testGetCar() {
      CarEntity entity = new CarEntity();
      entity.setId(1);
      entity.setName("ZEN");

      Car car = utilityMapper.getCar(entity);

      assertEquals(entity.getId(), car.getId());
      assertEquals(entity.getName(), car.getName());		
   }
}

运行以下命令测试映射。

mvn clean test

命令成功后。验证输出。

mvn clean test
[INFO] Scanning for projects...
...
[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ mapping ---
[INFO] Surefire report directory: \mvn\mapping\target\surefire-reports

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running com.tutorialspoint.mapping.CarMapperTest
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.256 sec
Running com.tutorialspoint.mapping.DeliveryAddressMapperTest
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.001 sec
Running com.tutorialspoint.mapping.StudentMapperTest
Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0 sec
Running com.tutorialspoint.mapping.UtilityMapperTest
Tests run: 5, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0 sec

Results :

Tests run: 9, Failures: 0, Errors: 0, Skipped: 0
...
广告

© . All rights reserved.