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);
    }
}
相关推荐
想用offer打牌6 小时前
RocketMQ如何防止消息丢失?
java·后端·架构·开源·rocketmq
嗝o゚7 小时前
鱼与熊掌可兼得?用Flutter+鸿蒙的混合架构破解性能与UI的世纪难题
flutter·架构·harmonyos
小小测试开发7 小时前
提升App UI自动化性能与效率:从脚本到架构的全链路优化指南
ui·架构·自动化
黄俊懿8 小时前
【深入理解SpringCloud微服务】Seata(AT模式)源码解析——@GlobalTransactional注解与@globalLock生效的原理
java·spring cloud·微服务·云原生·架构·系统架构·架构师
黄俊懿9 小时前
【深入理解SpringCloud微服务】Seata(AT模式)源码解析——开启全局事务
java·数据库·spring·spring cloud·微服务·架构·架构师
宇擎智脑科技10 小时前
Flutter 对接高德地图 SDK 适配鸿蒙踩坑记录与通信架构解析
flutter·架构·harmonyos
Xの哲學10 小时前
Linux DRM 架构深度解析
linux·服务器·算法·架构·边缘计算
Tezign_space10 小时前
抖音AI运营工具技术实践:特赞内容矩阵架构与300%效率提升方案
人工智能·架构·aigc·内容运营·抖音·ai营销工具·特赞
亿坊电商10 小时前
无人共享茶室智慧化破局:24H智能接单系统的架构实践与运营全景!
大数据·人工智能·架构
martinzh11 小时前
AI工具选择困难症?Spring AI帮你省掉64%的令牌费用
架构