零配置,零麻烦:MapStruct 的轻松对象映射之旅

简介: 零配置,零麻烦:MapStruct 的轻松对象映射之旅

欢迎来到我的博客,代码的世界里,每一行都是一个故事


前言

你是否曾为繁琐的对象映射代码而感到头疼?MapStruct 登场了!它不仅是 Java 开发者的得力助手,更是一个能够消除样板代码的魔法师。在这篇博客中,我们将一同踏上 MapStruct 的奇妙之旅,解锁它的神奇技能,让你的代码更为简洁、高效。

MapStruct是什么

MapStruct 是一个用于 Java 编程语言的对象映射框架,它的主要目标是简化 Java bean 类型之间的映射过程。在软件开发中,经常需要将一个对象的数据映射到另一个对象,而 MapStruct 通过注解处理器的方式,根据开发者提供的映射规则自动生成映射代码,从而减少手动编写重复、繁琐的映射代码的工作。

MapStruct 的定位是提供一种高性能、可扩展、易用的对象映射解决方案。相比其他对象映射框架,MapStruct 有以下优势:

  1. 性能优越: 由于 MapStruct 生成的映射代码是静态的,在编译期间就已经生成,因此它的性能通常比运行时反射的映射框架更高效。
  2. 可读性和维护性: MapStruct 生成的映射代码相对清晰简洁,易于阅读和维护。生成的代码包含了开发者定义的映射规则,也支持自定义转换逻辑。
  3. 类型安全: MapStruct 在编译期间就能够检测到潜在的映射错误,提供了类型安全性,减少了在运行时可能发生的错误。
  4. 灵活性: 支持自定义转换器,开发者可以通过注解指定特定的映射规则,也可以手动编写转换器以满足特定需求。

总体而言,MapStruct 是一款强大的对象映射框架,适用于各种 Java 项目,尤其在需要处理大量对象映射的场景下,能够提高开发效率并保证映射代码的质量。

快速上手:基础映射

快速上手 MapStruct 的基础映射需要完成一些简单的步骤。以下是一个基本的示例,演示如何创建一个简单的映射。

假设有两个类 SourceTarget,它们具有相似的字段,我们希望将一个对象映射到另一个对象。

  1. 引入 MapStruct 依赖:
    在项目的 pom.xml 文件中,添加 MapStruct 的依赖:
<dependencies>
    <!-- 其他依赖 -->
    <dependency>
        <groupId>org.mapstruct</groupId>
        <artifactId>mapstruct</artifactId>
        <version>1.4.2.Final</version> <!-- 查看最新版本 -->
    </dependency>
</dependencies>
  1. 配置 Maven 插件:
    pom.xml 中,添加 MapStruct 的 Maven 插件配置:
<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <configuration>
                <source>1.8</source> <!-- 适配你的 Java 版本 -->
                <target>1.8</target> <!-- 适配你的 Java 版本 -->
            </configuration>
        </plugin>
        <plugin>
            <groupId>org.mapstruct</groupId>
            <artifactId>mapstruct-maven-plugin</artifactId>
            <version>1.4.2.Final</version> <!-- 查看最新版本 -->
            <executions>
                <execution>
                    <goals>
                        <goal>compile</goal>
                    </goals>
                    <configuration>
                        <sourceDirectory>src/main/java</sourceDirectory>
                        <targetDirectory>target/generated-sources/mapstruct</targetDirectory>
                    </configuration>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>
  1. 创建源和目标类:
// Source 类
public class Source {
    private String name;
    private int age;
    // Getters and setters
}
// Target 类
public class Target {
    private String name;
    private int age;
    // Getters and setters
}
  1. 创建映射接口:
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
@Mapper
public interface SourceTargetMapper {
    @Mapping(source = "name", target = "name")
    @Mapping(source = "age", target = "age")
    Target sourceToTarget(Source source);
}
  1. 在上述代码中,@Mapper 注解表示这是一个 MapStruct 映射接口。@Mapping 注解用于指定源对象和目标对象字段的映射关系。
  2. 生成映射代码:
    在 Maven 项目中,运行以下 Maven 命令:
mvn clean install
  1. 这将触发 MapStruct 的注解处理器生成映射代码。

以上就是一个简单的 MapStruct 映射示例。请注意,这只是一个入门级的例子,MapStruct 还支持更复杂的映射,包括集合映射、嵌套映射等。通过适当的注解和配置,你可以灵活地定义映射规则,以满足项目的需求。

高级映射技巧

在 MapStruct 中,你可以使用高级映射技巧来处理复杂类型的映射,并定义自定义映射逻辑。以下是一些示例:

1. 针对复杂类型的映射:

假设有一个包含复杂类型的类 Person,其中包含了 Address 类型的地址信息。我们希望将 Person 类型映射到 PersonDTO 类型。

// Person 类
public class Person {
    private String name;
    private Address address;
    // Getters and setters
}
// Address 类
public class Address {
    private String city;
    private String street;
    // Getters and setters
}
// PersonDTO 类
public class PersonDTO {
    private String name;
    private String city;
    // Getters and setters
}

然后,创建映射接口并定义映射规则:

import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
@Mapper
public interface PersonMapper {
    @Mapping(source = "name", target = "name")
    @Mapping(source = "address.city", target = "city")
    PersonDTO personToPersonDTO(Person person);
}

在上述代码中,通过使用点号 . 来表示嵌套属性的映射关系,你可以轻松地处理复杂类型的映射。

2. 自定义映射逻辑:

有时候,你可能需要自定义映射逻辑以满足特定的需求。例如,如果需要将 Date 类型转换成字符串类型,可以使用自定义的转换器。

import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.factory.Mappers;
import java.text.SimpleDateFormat;
@Mapper
public interface CustomMapper {
    CustomMapper INSTANCE = Mappers.getMapper(CustomMapper.class);
    @Mapping(source = "date", target = "formattedDate", qualifiedByName = "dateFormat")
    Target customMapping(Source source);
    String dateFormat(java.util.Date date);
    class Target {
        private String formattedDate;
        // Getter and setter
    }
    class Source {
        private java.util.Date date;
        // Getter and setter
    }
}

在上述例子中,通过在映射接口中定义名为 dateFormat 的方法,并在 @Mapping 注解中使用 qualifiedByName 属性,实现了对 Date 类型的自定义转换。

这些是一些高级映射技巧的简单示例。MapStruct 提供了丰富的注解和配置选项,可以满足各种映射需求。根据项目的具体情况,你可以进一步探索 MapStruct 的文档以了解更多高级用法。

MapStruct 的进阶用法

MapStruct 提供了一些进阶用法,包括构造函数映射、嵌套映射和集合映射。下面分别介绍这些进阶用法:

1. 构造函数映射:

在某些情况下,你可能希望使用构造函数进行映射。MapStruct 允许你在映射接口中使用构造函数映射,这样可以更加灵活地处理对象创建过程。

假设有一个类 Person,它有一个包含多个参数的构造函数,我们希望将其映射到 PersonDTO 类型。

// Person 类
public class Person {
    private String name;
    private int age;
    // 构造函数
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    // Getters and setters
}
// PersonDTO 类
public class PersonDTO {
    private String name;
    private int age;
    // 构造函数
    public PersonDTO(String name, int age) {
        this.name = name;
        this.age = age;
    }
    // Getters and setters
}

然后,在映射接口中使用构造函数映射:

import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
@Mapper
public interface PersonMapper {
    @Mapping(target = "name", source = "name")
    @Mapping(target = "age", source = "age")
    PersonDTO personToPersonDTO(Person person);
}

MapStruct 会自动识别构造函数映射的关系,并生成相应的映射代码。

2. 嵌套映射:

MapStruct 支持嵌套映射,允许你在对象之间建立更复杂的映射关系。假设有一个嵌套的类结构,如 Order 包含 Customer,我们希望将 Order 映射到 OrderDTO,同时也映射 CustomerCustomerDTO

// Order 类
public class Order {
    private String orderId;
    private Customer customer;
    // Getters and setters
}
// Customer 类
public class Customer {
    private String name;
    private String address;
    // Getters and setters
}
// OrderDTO 类
public class OrderDTO {
    private String orderId;
    private CustomerDTO customer;
    // Getters and setters
}
// CustomerDTO 类
public class CustomerDTO {
    private String name;
    private String address;
    // Getters and setters
}

在映射接口中进行嵌套映射:

import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
@Mapper
public interface OrderMapper {
    @Mapping(source = "customer", target = "customer")
    OrderDTO orderToOrderDTO(Order order);
    @Mapping(source = "name", target = "name")
    @Mapping(source = "address", target = "address")
    CustomerDTO customerToCustomerDTO(Customer customer);
}

MapStruct 会根据映射接口中的定义自动生成嵌套映射代码。

3. 集合映射:

MapStruct 也支持集合的映射。假设有一个类 Library 包含了多个书籍 Book,我们希望将 Library 映射到 LibraryDTO,同时也映射其中的书籍列表。

// Book 类
public class Book {
    private String title;
    private String author;
    // Getters and setters
}
// Library 类
public class Library {
    private List<Book> books;
    // Getters and setters
}
// LibraryDTO 类
public class LibraryDTO {
    private List<BookDTO> books;
    // Getters and setters
}
// BookDTO 类
public class BookDTO {
    private String title;
    private String author;
    // Getters and setters
}

在映射接口中进行集合映射:

import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
@Mapper
public interface LibraryMapper {
    @Mapping(source = "books", target = "books")
    LibraryDTO libraryToLibraryDTO(Library library);
    @Mapping(source = "title", target = "title")
    @Mapping(source = "author", target = "author")
    BookDTO bookToBookDTO(Book book);
}

MapStruct 会根据映射接口中的定义自动生成集合映射代码。

这些是 MapStruct 的一些进阶用法,它们能够帮助你更灵活地处理复杂的映射场景。根据项目需求,你可以结合这些技巧,定制符合你业务逻辑的映射规则。

伪出错

1、报错 java.lang.ClassNotFoundException: Cannot find implementation for fun.todoitbo.botally.convert.TbBillConvert

这里要观察你的@Mapper注解,你可能错把mybatis中的@Mapper当成宝了

2、映射返回的结果都是null

出现上面的情况,要观察,是否存在目标类上没有set,get方法

3、我修改了源类或者目标类但是他没有生效

这里你需要clear一下,重新启动,因为它的实现方法只生成一次

结语:

通过本文的深度探索,相信你将对 MapStruct 有了全新的认识,并能够在你的项目中充分发挥它的威力。让我们一同掌握这门“魔法”,让代码变得更加清爽、优雅!

相关文章
|
SQL Java 数据库连接
Mybatis知识【Mapper代理开发&核心配置】第三章
Mybatis知识【Mapper代理开发&核心配置】第三章
|
1月前
|
XML Java 数据格式
Spring从入门到入土(xml配置文件的基础使用方式)
本文详细介绍了Spring框架中XML配置文件的使用方法,包括读取配置文件、创建带参数的构造对象、使用工厂方法和静态方法创建对象、对象生命周期管理以及单例和多例模式的测试。
84 7
Spring从入门到入土(xml配置文件的基础使用方式)
|
3月前
|
Java Spring 开发者
Spring 框架配置属性绑定大比拼:@Value 与 @ConfigurationProperties,谁才是真正的王者?
【8月更文挑战第31天】Spring 框架提供 `@Value` 和 `@ConfigurationProperties` 两种配置属性绑定方式。`@Value` 简单直接,适用于简单场景,但处理复杂配置时略显不足。`@ConfigurationProperties` 则以类级别绑定配置,简化代码并更好组织配置信息。本文通过示例对比两者特点,帮助开发者根据具体需求选择合适的绑定方式,实现高效且易维护的配置管理。
51 0
|
4月前
|
安全 IDE Java
MapStruct-JavaBean映射工具使用指南
MapStruct-JavaBean映射工具使用指南
|
6月前
|
SQL Java 数据库连接
15:MyBatis对象关系与映射结构-Java Spring
15:MyBatis对象关系与映射结构-Java Spring
108 4
|
6月前
|
XML Java Maven
Spring框架学习 -- 创建与使用
Spring框架学习 -- 创建与使用
34 0
|
6月前
|
Java 关系型数据库 MySQL
高级对象装配:解析Spring创建复杂对象的秘诀
高级对象装配:解析Spring创建复杂对象的秘诀
58 0
高级对象装配:解析Spring创建复杂对象的秘诀
|
Java 程序员 Spring
Spring文件第四课SpringIOC 的三种方案利用注解的方式.(一)
Spring文件第四课SpringIOC 的三种方案利用注解的方式.(一)
89 0
|
11月前
|
存储 Java 编译器
【Spring】透过Spring源码查看Bean的命名转换规则
【Spring】透过Spring源码查看Bean的命名转换规则
66 0
【Spring】透过Spring源码查看Bean的命名转换规则
|
Java Spring
Spring文件第四课SpringIOC 的三种方案利用注解的方式.(二)
Spring文件第四课SpringIOC 的三种方案利用注解的方式.(二)
62 0