当前位置: 首页 > news >正文

【SpringBoot】26 实体映射工具(MapStruct)

Gitee 仓库

https://gitee.com/Lin_DH/system

介绍

现状

为了让应用程序的代码更易于维护,通常会将项目进行分层。在《阿里巴巴 Java 开发手册》中,推荐分层如下图所示:
在这里插入图片描述
每层都有对应的领域模型,即不同类型的 Bean。

  • DO(Data Object):与数据库表结构一一对应,通过 DAO 层向上传输数据源对象。
  • DTO(Data Transfer Object):数据传输对象,Service 或 Manager 向外传输的对象。
  • BO(Business Object):业务对象,由 Service 层输出的封装业务逻辑的对象。
  • AO(Application Object):应用对象,在 Web 层与 Service 层之间抽象的复用对象模型,极为贴近展示层,复用度不高。
  • VO(View Object):显示层对象,通常是 Web 向模板渲染引擎层传输的对象。
  • Query:数据查询对象,各层接收上层的查询请求。超过两个参数的查询封装,禁止使用 Map 类进行传输。

痛点

由于代码分层的原因,就会导致代码中有多种 Bean,如 UserVO,UserDTO,UserDO 等,并且经常发生各种 VO / DTO / DO 之间的转换。从而产生很多 vo.setUsername(dto.getUsername()) 的代码。当字段多了不仅容易出错,而且很浪费开发时间。也有使用 BeanUtils.copyProperties() 进行转换,这样虽然减少了开发时间和代码,但依然存在问题。如:1)利用反射导致性能不好;2)不同名称的属性无法直接进行映射。

解决方案

本次使用的 Java 实体对象映射框架是 MapStruct 。MapStruct基于 JSR 269 的 Java 注解处理器,用于生成类型安全,高性能,无依赖的 Bean 映射代码,自动生成对象的代码,使用便捷,性能优越。

特点

  • 1)通过 getter / setter 进行字段拷贝,而不是利用反射机制。
  • 2)字段名称相同直接转换,名称不同使用 @Mapping 注解标识。

区别

与动态映射框架相比,MapStruct 的优势:

  • 1)使用普通的 getter / setter 方法,而不是反射机制,执行更快,性能更好。
  • 2)编译时类型安全。
  • 3)清晰的错误提示信息。

依赖

pom.xml

需要引入 mapstruct 和 mapstruct-processor,同时 scope 设置为 provided ,即它只影响到编译,测试阶段。

<dependency><groupId>org.mapstruct</groupId><artifactId>mapstruct</artifactId><version>1.5.0.Final</version><scope>provided</scope>
</dependency><dependency><groupId>org.mapstruct</groupId><artifactId>mapstruct-processor</artifactId><version>1.5.0.Final</version><scope>provided</scope>
</dependency>

代码实现

第一步:编写 Student 实体类

Student.java

package com.lm.system.common;import lombok.*;import java.io.Serializable;
import java.util.Date;/*** @author DUHAOLIN* @date 2024/11/12*/
@Data
@Builder
public class Student implements Serializable {private static final long serialVersionUID = 1L;private Integer id;private String name;private Integer age;private String gender;private Date createTime;}

第二步:编写 StudentVO 实体类

StudentVO.java

package com.lm.system.common.dto;import lombok.Data;/*** @author DUHAOLIN* @date 2024/11/12*/
@Data
public class StudentVO {private Integer userId;private String username;private Integer age;private String gender;}

第三步:编写实体类转换接口

StudentConvert.java

package com.lm.system.convert;import com.lm.system.common.Student;
import com.lm.system.common.dto.StudentVO;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Mappings;
import org.mapstruct.factory.Mappers;/*** @author DUHAOLIN* @date 2024/11/12*/
@Mapper
public interface StudentConvert {/*** 获取该类自动生成的实体类实例*/StudentConvert INSTANCES = Mappers.getMapper(StudentConvert.class);@Mappings({@Mapping(source = "id", target = "userId"),@Mapping(source = "name", target = "username")})StudentVO toStudentVO(Student student);}

第四步:编写测试类

MapStructTest.java

package com.lm.system.test;import com.lm.system.common.Student;
import com.lm.system.common.dto.StudentVO;
import com.lm.system.convert.StudentConvert;
import org.junit.Test;import java.util.Date;/*** @author DUHAOLIN* @date 2024/11/12*/
public class MapStructTest {@Testpublic void testStudent() {Student student = getStudent();System.out.println(student);StudentVO studentVO = StudentConvert.INSTANCES.toStudentVO(student);System.out.println(studentVO);}private Student getStudent() {return Student.builder().id(1).name("Tom").age(18).gender("男").createTime(new Date()).build();}}

效果图

在这里插入图片描述

属性处理

简单属性

当 gender 传入的是男或女,需要转换成对应的0或1,再传入数据库时,则需要进行处理。

StudentConvert.java

@Mappings({@Mapping(source = "id", target = "userId"),@Mapping(source = "name", target = "username"),@Mapping(target = "gender", expression = "java(student.getGender() == \"男\" ? \"0\" : \"1\")")
})
StudentVO toStudentVO(Student student);

在这里插入图片描述

复杂属性

限制输入年龄的数值。

StudentConvert.java

package com.lm.system.convert;import com.lm.system.common.Student;
import com.lm.system.common.dto.StudentVO;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Mappings;
import org.mapstruct.Named;
import org.mapstruct.factory.Mappers;/*** @author DUHAOLIN* @date 2024/11/12*/
@Mapper
public interface StudentConvert {/*** 获取该类自动生成的实体类实例*/StudentConvert INSTANCES = Mappers.getMapper(StudentConvert.class);@Mappings({@Mapping(source = "id", target = "userId"),@Mapping(source = "name", target = "username"),@Mapping(target = "gender", expression = "java(student.getGender() == \"男\" ? \"0\" : \"1\")"),@Mapping(source = "age", target = "age", qualifiedByName = "transferAge")})StudentVO toStudentVO(Student student);@Named("transferAge")default Integer transferAge(Integer age) {if (age < 0) {return 0;}else if (age > 120){return 120;}else {return age;}}}

在这里插入图片描述

Spring中使用

如果在 Spring 中使用,需要修改组件模型为 spring,可以通过 pom.xml 参数修改,也可以通过注解修改。修改后会在实现类上添加 @Component 注解,从而成为一个 Bean,加入 Spring 容器中。

StudentConvert.java

@Mapper(componentModel = "spring")
public interface StudentConvert {}

报错

如果遇到报错:java.lang.NoSuchMethodError,则在 IDEA 右侧的 Maven 选项中,运行 clean 和 compile,再进行重试。
在这里插入图片描述

项目结构图

在这里插入图片描述

参考链接

推荐一款Java实体映射工具—mapstruct:【https://www.cnblogs.com/lvmengtian/p/14594185.html】
【springboot进阶】优雅使用 MapStruct 进行类复制:【https://blog.csdn.net/lrb0677/article/details/127838138】
芋道 Spring Boot 对象转换 MapStruct 入门:【https://www.iocoder.cn/Spring-Boot/MapStruct/?self】

相关文章:

【SpringBoot】26 实体映射工具(MapStruct)

Gitee 仓库 https://gitee.com/Lin_DH/system 介绍 现状 为了让应用程序的代码更易于维护&#xff0c;通常会将项目进行分层。在《阿里巴巴 Java 开发手册》中&#xff0c;推荐分层如下图所示&#xff1a; 每层都有对应的领域模型&#xff0c;即不同类型的 Bean。 DO&…...

分层架构 IM 系统之架构演进

在电商业务日活几百万的情况下&#xff0c;IM 系统采用分层架构方式&#xff0c;如下图。 分层架构的 IM 系统&#xff0c;整体上包含了【终端层】、【入口层】、【业务逻辑层】、【路由层】、【数据访问层】和【存储层】&#xff0c;我们在上篇文章&#xff08;分层架构 IM 系…...

基于YOLOv8深度学习的医学影像阿尔兹海默症检测诊断系统研究与实现(PyQt5界面+数据集+训练代码)

阿尔茨海默症&#xff08;Alzheimer’s disease&#xff09;是一种常见的神经退行性疾病&#xff0c;主要表现为记忆丧失、认知能力下降以及行为和人格改变。随着全球老龄化问题的加剧&#xff0c;阿尔茨海默症的发病率也在逐年上升&#xff0c;给患者及其家庭带来了巨大的经济…...

【支持向量机(SVM)】:相关概念及API使用

文章目录 1 SVM相关概念1.1 SVM引入1.1.1 SVM思想1.1.2 SVM分类1.1.3 线性可分、线性和非线性的区分 1.2 SVM概念1.3 支持向量概念1.4 软间隔和硬间隔1.5 惩罚系数C1.6 核函数 2 SVM API使用2.1 LinearSVC API 说明2.2 鸢尾花数据集案例2.3 惩罚参数C的影响 1 SVM相关概念 1.1…...

Android kotlin之配置kapt编译器插件

配置项目目录下的gradle/libs.versions.toml文件&#xff0c;添加kapt配置项&#xff1a; 在模块目录下build.gradle.kt中增加 plugins {alias(libs.plugins.android.application)alias(libs.plugins.jetbrains.kotlin.android)// 增加该行alias(libs.plugins.jetbrains.kotl…...

时序数据库TDEngine

TDengine 是一款开源、高性能、云原生的时序数据库&#xff08;Time Series Database, TSDB&#xff09;, 它专为物联网、车联网、工业互联网、金融、IT 运维等场景优化设计。同时它还带有内建的缓存、流式计算、数据订阅等系统功能&#xff0c;能大幅减少系统设计的复杂度&…...

jd-easyflow中inclusive的用法

在jd-easyflow中&#xff0c;inclusive通常与流程中的条件分支&#xff08;conditions&#xff09;配置相关&#xff0c;用于控制多个条件分支的执行逻辑。当conditionType设置为inclusive时&#xff0c;表示多个条件分支中的所有条件都会被评估&#xff0c;而不是像exclusive那…...

sqlmap图形化安装使用(附文件)

1.需要python环境&#xff0c;我这里就不教如何安装python环境了。 2.下载压缩包并且解压 3. 凭自己喜好选择大窗口小窗口 4.进入图形化界面后&#xff0c;1.输入url地址。2.选择要执行的操作。3.构造命令语句 5.点击一把梭&#xff0c;然后就可以发现出结果了 6. 对于喜欢自己…...

从二维到一维:动态规划矩阵问题的优化之道

动态规划中的矩阵问题是非常经典的应用场景&#xff0c;比如最小路径和问题。这类问题很自然地可以想到使用二维 dp 数组来求解。 我们定义&#xff1a; dp[i][j] 表示从矩阵的第 i行第 j列到右下角的最小路径和。 基本解法 求解过程从右下角开始&#xff0c;向左上角遍历&am…...

计算机视觉(CV):让机器看懂世界

引言 计算机视觉&#xff08;Computer Vision, CV&#xff09;是人工智能的重要领域&#xff0c;致力于让机器能够“看懂”世界。CV技术广泛应用于自动驾驶、医疗影像、安防监控和娱乐领域&#xff0c;正在改变我们的生活方式。 本文将从基本概念、技术方法、应用场景和发展方向…...

记录下,用油猴Tampermonkey监听所有请求,绕过seesion

油猴Tampermonkey监听所有请求&#xff0c;绕过seesion 前因后果脚本编写 前因后果 原因是要白嫖一个网站的接口&#xff0c;这个接口的页面入口被隐藏掉了&#xff0c;不能通过页面调用&#xff0c;幸好之前有想过逆向破解通过账号密码模拟登录后拿到token&#xff0c;请求该…...

服务器产品

一 存储产品 3.1 3PAR 3.2 X10000 3.3 SAN Switch 3.4 Nimble 3.5 SimpliVity 3.6 XP 3.7 MSA 3.8 StoreOnce 3.9 StoreEver 3.10 StoreBlade 3.11 StoreEasy&#xff08;WindowsNAS&#xff09; 3.12 JBOD 3.13 CB 二 服务器产品 4.1 红牌服务器 4.1.1 红牌…...

pyhton django web集群基于linux定时任务

基于django management/commands目录下的脚本 from django.core.management import BaseCommand import logging import uuid from pia.utils.cache import reset_redis_expire from pia.utils.reids_key import TASK_KEYlogging logging.getLogger(task)""" …...

探索 Python 字典的奥秘:Future 对象为何能成为字典的键?

本质在于作为字典的key能不能执行hash(key) 问题 import concurrent.futuresdef task(n):return n * n# 创建一个线程池 with concurrent.futures.ThreadPoolExecutor() as executor:# 提交任务并获取 Future 对象future_to_num {executor.submit(task, i): i for i in rang…...

多品牌摄像机视频平台EasyCVR视频融合平台+应急布控球:打造城市安全监控新体系

在当今快速发展的智慧城市和数字化转型浪潮中&#xff0c;视频监控技术已成为提升公共安全、优化城市管理、增强应急响应能力的重要工具。EasyCVR视频监控平台以其强大的多协议接入能力和多样化的视频流格式分发功能&#xff0c;为用户提供了一个全面、灵活、高效的视频监控解决…...

Spark 中 RDD checkpoint 是通过启动两个独立的 Job 完成的。

在 Spark 中&#xff0c;RDD checkpoint 是通过启动两个独立的 Job 完成的。这两个 Job 分别用于生成 checkpoint 数据和更新依赖关系。下面从源码角度深入分析这个机制。 1. 为什么需要两个 Job&#xff1f; 当调用 RDD.checkpoint() 后&#xff1a; 第一个 Job&#xff1a;…...

如何下载TikTok视频没有水印

随着短视频平台的普及&#xff0c;TikTok&#xff08;抖音国际版&#xff09;成为了全球最受欢迎的社交媒体平台之一。它吸引了无数创作者发布自己的短视频内容&#xff0c;内容涵盖了舞蹈、搞笑、挑战、教程、旅行等各个方面。与此用户也常常希望能够下载自己喜欢的TikTok视频…...

天童美语:提升孩子的自信心的方法

每个孩子都渴望展翅高飞&#xff0c;但在成长的旅途中&#xff0c;难免会遇到风雨。不自信&#xff0c;就像一层薄雾&#xff0c;有时悄悄笼罩在孩子心头&#xff0c;阻碍了他们向阳而生的脚步。宁波天童教育认为&#xff0c;身为家长&#xff0c;我们的使命不仅是孩子的庇护伞…...

【网络编程】字节序:大端序和小端序

端序&#xff08;Endianness&#xff09;&#xff0c;又称字节顺序&#xff0c;又称尾序&#xff0c;在计算机科学领域中&#xff0c;指存储器中或在数字通信链路中&#xff0c;组成多字节的字的字节的排列顺序。 在几乎所有的机器上&#xff0c;多字节对象都被存储为连续的字…...

视频融合×室内定位×数字孪生

随着物联网技术的迅猛发展&#xff0c;室内定位与视频融合技术在各行各业中得到了广泛应用。不仅能够提供精确的位置信息&#xff0c;还能通过实时视频监控实现全方位数据的可视化。 与此同时&#xff0c;数字孪生等技术的兴起为智慧城市、智慧工厂等应用提供了强大支持&#…...

AI 驱动单元测试生成:智能优先级与自动化验证实践

1. 项目概述如果你和我一样&#xff0c;长期在维护一个中大型的 TypeScript 项目&#xff0c;那么“补单元测试”这件事&#xff0c;大概率是你技术债清单上那个永远在滚动、却很少被真正划掉的任务。手动写测试枯燥耗时&#xff0c;尤其是面对那些遗留的、逻辑复杂的业务函数时…...

Gemini3.1Pro发布:多模态AI再进化

如果你最近也在跟踪 2026 年的 AI 动态&#xff0c;应该会发现一个很明显的变化&#xff1a;大模型的竞争重点&#xff0c;已经从“会不会生成内容”&#xff0c;转向“能不能真正理解复杂任务并参与工作流”。像KULAAI&#xff08;dl.877ai.cn&#xff09; 这类 AI 聚合平台&a…...

Agnix:为AI智能体打造安全可控的操作系统级执行环境

1. 项目概述&#xff1a;从“智能体”到“操作系统”的范式跃迁最近在开源社区里&#xff0c;一个名为agent-sh/agnix的项目引起了我的注意。乍一看这个名字&#xff0c;agent和agnix的组合&#xff0c;很容易让人联想到这是又一个基于大语言模型的智能体&#xff08;Agent&…...

智慧港口高风险作业AI实时监督技术实操解析

在智慧港口建设中&#xff0c;集装箱堆场、高风险作业的安全管控是核心重点&#xff0c;其中皮带运输、高风险作业&#xff08;吊装、动火、高处、有限空间等&#xff09;的安全保障&#xff0c;是港口运维的关键。当前&#xff0c;港口高风险作业普遍面临痛点&#xff1a;人工…...

ngx_http_create_request

1 定义 ngx_http_create_request 函数 定义在 ./nginx-1.24.0/src/http/ngx_http_request.cngx_http_request_t * ngx_http_create_request(ngx_connection_t *c) {ngx_http_request_t *r;ngx_http_log_ctx_t *ctx;ngx_http_core_loc_conf_t *clcf;r ngx_http_…...

ElevenLabs账号被限频?紧急修复手册:3分钟绕过Rate Limit限制,解锁Pro级语音并发权限

更多请点击&#xff1a; https://intelliparadigm.com 第一章&#xff1a;ElevenLabs超写实语音生成教程 ElevenLabs 是当前业界领先的 AI 语音合成平台&#xff0c;其模型在语调自然度、情感表达力与跨语言一致性方面表现卓越。本章将指导你完成从 API 接入到高质量语音生成的…...

基于Ollama与Stable Diffusion的Discord AI机器人本地部署指南

1. 项目概述&#xff1a;一个能聊能画的Discord AI机器人 最近在折腾一个挺有意思的玩意儿&#xff1a;一个部署在自己电脑上的Discord机器人&#xff0c;它不仅能像ChatGPT一样跟你聊天&#xff0c;还能根据你的描述生成图片。这个项目的核心&#xff0c;是把两个当下很火的开…...

从被看不起到被追更:《凰标》的逆袭就是行业缩影@凤凰标志

——《凰标》如何一刀劈开文娱偏见无资本即为小众&#xff0c;无热度即为劣质&#xff0c;无流量即为无用。 这条铁律&#xff0c;曾压弯无数民间创作者的笔。一、被看不起的开局&#xff1a;民间创作的“三无原罪”行业默认《凰标》现实顶级 IP 加持零 IP&#xff0c;纯原创豪…...

本地AI任务编排工具AgentForge:从看板管理到多代理协作

1. 项目概述&#xff1a;一个能调度AI编码代理的本地看板工具如果你和我一样&#xff0c;日常开发中经常需要让Claude Code这类AI编码助手去执行一些重复性的代码审查、重构或者生成任务&#xff0c;并且希望这些任务能像CI/CD流水线一样被编排、调度和监控&#xff0c;那么你一…...

Unity(十六)切换场景及鼠标相关

场景切换空间命名&#xff1a;using UnityEngine.SceneManagement;直接用代码切换场景有问题要把场景加入到场景列表之中SceneList哪个场景在前面&#xff0c;谁在运行时就会首先进入过时方法Application.LoadLevel()if (Input.GetKeyDown(KeyCode.Space)) {SceneManager.LoadS…...