MapStruct 对象转换工具【DDD 架构】

文章目录

    • 一、前言
    • 二、对象模型
      • [1. DTO 数据传输对象](#1. DTO 数据传输对象)
      • [2. BO 业务对象](#2. BO 业务对象)
      • [3. PO 持久化对象](#3. PO 持久化对象)
      • [4. VO 值对象](#4. VO 值对象)
    • [三、MapStruct 对象转换](#三、MapStruct 对象转换)
      • [1. 工具介绍](#1. 工具介绍)
      • [2. 代码演示](#2. 代码演示)

一、前言

上篇我们学习了 DDD 架构,从上到下依次是:用户接口层、应用层、领域层和基础层。

那么不同层的实体类是怎么定义的呢?

这些实体类之间又该如何互相转换?

请记住这两个问题。

本篇由你的栈☞

带你一探究竟。

二、对象模型

在软件开发中,DTO、BO、PO、VO 是常见的对象模型,用于在不同的层次和场景中传递和处理数据。

の......咳咳,实际上都是实体类,只是名字叫的花里胡哨,但是为了开发更规范,来?

1. DTO 数据传输对象

官方的回答(它的废话):用于在用户接口层传输数据的对象,避免直接暴露领域模型给外部,减少不必要的数据传输,只传递需要的字段。

说人话:在 Controller 用户接口层,将前端传过来的数据封装为DTO,对应的实体类的名字应为 XXXDTO。

java 复制代码
public class UserDTO {
    private Long id;
    private String name;
    private String email;

    // Getters and Setters
}
java 复制代码
@RestController
@RequestMapping("/users")
public class UserController {
    private UserService userService;

    // 接收前端传递的 DTO
    @PostMapping
    public ResponseEntity<String> createUser(@RequestBody UserDTO userDTO) {
        userService.createUser(userDTO);
        return ResponseEntity.ok("User created successfully");
    }
}

2. BO 业务对象

官方的回答(它的废话):封装了业务逻辑的对象,包含与业务相关的状态和行为。

说人话:在 应用层和领域层,将上一层传过来的数据封装为BO,对应的实体类的名字应为 XXXBO。

3. PO 持久化对象

官方的回答(它的废话):与数据库表直接映射的对象,字段与数据库表的列一一对应。

说人话:在DAO 基础层,将上一层传过来的数据封装为PO,对应的实体类的名字应为 XXXPO。

4. VO 值对象

官方的回答(它的废话):用于标识一个不可变的对象,一旦创建就不能修改,通常用于展示数据。

说人话:各层返回的数据都用 VO 包装,对应的实体类的名字应为 XXXVO。

java 复制代码
@Service
public class UserService {
    // 模拟从数据库获取用户信息
    public UserVO getUserVO(Long userId) {
        // 假设从数据库查询到用户信息
        UserPO userPO = new UserPO(1L, "John Doe", "john.doe@example.com");

        // 将 PO 转换为 VO
        return new UserVO(userPO.getId(), userPO.getName(), userPO.getEmail());
    }
}
java 复制代码
@RestController
@RequestMapping("/users")
public class UserController {
    private final UserService userService;

    @Autowired
    public UserController(UserService userService) {
        this.userService = userService;
    }

    @GetMapping("/{id}")
    public ResponseEntity<UserVO> getUser(@PathVariable Long id) {
        UserVO userVO = userService.getUserVO(id);
        return ResponseEntity.ok(userVO);
    }
}

三、MapStruct 对象转换

1. 工具介绍

在业务流程进行中,数据想要往下传递,首先得保证数据类型一致,那么不同的实体类之间就需要互相转换,如果不使用 MapStruct,我们的转换方法就是手动复制 DTO 数据到 BO,代码耦合度较高,且编码效率低。

MapStruct 是一个用于 Java Bean 映射的代码生成库。它通过注解自动生成对象转换代码,减少手动编写映射逻辑的工作量。

特点:

① 高效,生成的代码是原生的 Java 方法调用,性能接近手写代码;

② 类型安全,编译时生成代码,避免运行时错误;

③ 易用,通过简单的注解配置,即可实现复杂映射。

2. 代码演示

① 引入依赖

xml 复制代码
<dependency>
    <groupId>org.mapstruct</groupId>
    <artifactId>mapstruct</artifactId>
    <version>1.5.5.Final</version> <!-- 使用最新版本 -->
</dependency>
<dependency>
    <groupId>org.mapstruct</groupId>
    <artifactId>mapstruct-processor</artifactId>
    <version>1.5.5.Final</version> <!-- 使用最新版本 -->
    <scope>provided</scope>
</dependency>

② 定义源对象和目标对象

java 复制代码
//源对象
public class User {
    private Long id;
    private String name;
    private String email;

    // Getters and Setters
}
java 复制代码
//目标对象
public class UserDTO {
    private Long id;
    private String name;
    private String email;

    // Getters and Setters
}

③ 定义映射接口

使用 @Mapper 注解定义一个映射接口,MapStruct 会自动生成实现类!

java 复制代码
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;

@Mapper
public interface UserMapper {
    // 获取映射器实例
    UserMapper INSTANCE = Mappers.getMapper(UserMapper.class);

    // 将 User 对象转换为 UserDTO 对象
    UserDTO toDTO(User user);

    // 将 UserDTO 对象转换为 User 对象
    User toEntity(UserDTO userDTO);
}

④ 使用映射器

java 复制代码
public class Main {
    public static void main(String[] args) {
        // 创建 User 对象
        User user = new User();
        user.setId(1L);
        user.setName("John Doe");
        user.setEmail("john.doe@example.com");

        // 使用映射器将 User 转换为 UserDTO
        UserDTO userDTO = UserMapper.INSTANCE.toDTO(user);

        // 打印结果
        System.out.println(userDTO);
    }
}
相关推荐
eqwaak01 小时前
基于Spring Cloud Alibaba的电商系统微服务化实战:从零到生产级部署
java·分布式·微服务·云原生·架构
冰火同学3 小时前
Spark架构都有那些组件
大数据·架构·spark
gordon~95 小时前
面试题-微服务
微服务·云原生·架构
小杨4045 小时前
springboot框架启动流程二(源码分析)
spring boot·后端·架构
云卷️6 小时前
微服务面试题及原理
java·后端·微服务·云原生·架构
摩尔线程6 小时前
SEKI —— 基于大型语言模型的自进化与知识启发式神经架构搜索
人工智能·语言模型·架构
瞬间动力6 小时前
1分钟简化理解单体、微服务、分布式和Serverless
java·分布式·微服务·架构·系统架构
WeiLai111210 小时前
面试基础---Spring Cloud微服务负载均衡架构
spring boot·分布式·后端·spring·spring cloud·面试·架构
码农汉子10 小时前
k8s架构及服务详解
容器·架构·kubernetes