mapstruct对象映射在Springboot3中这样用就对了
mapstruct对象映射在Springboot3中这样用就对了

我们在日常的开发工作中,经常会遇到Entity转VO,VO转Entity或其它对象的相互映射赋值。在不同的对象间进行属性赋值有多种方式,今天我们来学习mapstruct在Springboot3中如何使用。今天的案例覆盖两种场景,一种是JavaBean没有使用lombok另外一种是使用了lombok,那么我们一起看这两种情况要如何进行配置才能正常使用。
完整代码在文章最后,如果觉得本篇文章对你有用,记得点赞、关注、收藏哦。你的支持是我持续更新的动力!
SpringBoot3专栏软件环境
- JDK17.0.12
- SpringBoot3.4.0
- mapstruct1.5.5.Final
- lombok1.18.34
- IDEA2024.2.0.2
我们先看本篇文章对应的项目结构,请看下图

1 父工程配置
<?xml version="1.0" encoding="UTF-8"?>
<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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>cn.itbeien</groupId>
<artifactId>springboot3-labs-master</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<!-- <parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.4.0</version>
</parent>-->
<modules>
<module>springboot-nacos</module>
<module>springboot-mybatis-plus</module>
<module>spingboot-mybatis</module>
<module>mybatis-generator</module>
<module>springboot-mybatis-nacos</module>
<module>dynamic-datasource-mybatis-plus</module>
<module>springboot-mapstruct</module>
<module>springboot-mapstruct-lombok</module>
</modules>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<nacos-config-spring-boot-starter-version>0.2.12</nacos-config-spring-boot-starter-version>
<lombok-version>1.18.34</lombok-version>
<mybatis-plus-spring-boot3-starter-version>3.5.9</mybatis-plus-spring-boot3-starter-version>
<mysql-connector-java-version>5.1.49</mysql-connector-java-version>
<spring-boot-dependencies-version>3.4.0</spring-boot-dependencies-version>
<mybatis-spring-boot-version>3.0.3</mybatis-spring-boot-version>
<mapstruct-verrsion>1.5.5.Final</mapstruct-verrsion>
<mapstruct-processor-version>1.5.5.Final</mapstruct-processor-version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot-dependencies-version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>com.alibaba.boot</groupId>
<artifactId>nacos-config-spring-boot-starter</artifactId>
<version>${nacos-config-spring-boot-starter-version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok-version}</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-spring-boot3-starter</artifactId>
<version>${mybatis-plus-spring-boot3-starter-version}</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql-connector-java-version}</version>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>${mybatis-spring-boot-version}</version>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>${mapstruct-verrsion}</version>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${mapstruct-processor-version}</version>
</dependency>
</dependencies>
</dependencyManagement>
</project>
2 JavaBean中不使用lombok
2.1 pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>cn.itbeien</groupId>
<artifactId>springboot3-labs-master</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>springboot-mapstruct</artifactId>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
</dependency>
</dependencies>
</project>
2.2 mapstruct 映射配置接口
属性映射接口中的entity和vo自己自行在文末的源码中进行查看,这里不做展示
package cn.itbeien.mapstruct.convert;
import cn.itbeien.mapstruct.entity.MerchantInfo;
import cn.itbeien.mapstruct.vo.BaseMerchantVO;
import cn.itbeien.mapstruct.vo.MerchantInfoVO;
import cn.itbeien.mapstruct.vo.SmallMerchantVO;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Mappings;
import org.mapstruct.factory.Mappers;
/**
* @author itbeien
* 项目网站:https://www.itbeien.cn
* 公众号:贝恩聊架构
* 全网同名,欢迎小伙伴们关注
* Copyright© 2024 itbeien
*/
@Mapper
public interface MerchantConvert {
MerchantConvert INSTANCE = Mappers.getMapper(MerchantConvert.class);
/**
* 实体类和VO属性名称相同
* @param merchantInfoVO
* @return
*/
MerchantInfo convertMerchant(MerchantInfoVO merchantInfoVO);
@Mappings({
@Mapping(source = "regName", target = "mercName"),
@Mapping(source = "merchantName",target = "mercNickName"),
@Mapping(source = "merLegal",target = "linkman"),
@Mapping(source = "industries",target = "mccId"),
@Mapping(source = "address",target = "merArea"),
@Mapping(source = "employeeNum",target = "employeeNum",defaultValue = "1"),
@Mapping(source = "merLegal",target = "corpReptName"),
@Mapping(source = "legalCode",target = "corpReptId"),
@Mapping(source = "address",target = "province"),
@Mapping(source = "address",target = "city"),
@Mapping(source = "addressDetail",target = "corpAddr"),
@Mapping(source = "accType",target = "mercSettAcctType"),
@Mapping(source = "account",target = "mercSettAcct"),
@Mapping(source = "accName",target = "mercSettAcctNm"),
@Mapping(source = "bankCode",target = "mercSettBank"),
@Mapping(source = "bankName",target = "mercSettBankNm"),
@Mapping(target = "merMode", expression = "java( cn.itbeien.mapstruct.enums.MerModeEnum.PERSON.getCode() )"),
@Mapping(source = "capital",target = "capital",defaultValue = "10"),
@Mapping(source = "rxm",target = "merIdRxm"),
@Mapping(source = "ghm",target = "merIdGhm"),
@Mapping(source = "syt",target = "merSyt"),
@Mapping(source = "hjz",target = "merHjz"),
@Mapping(source = "mtz",target = "merMtz"),
@Mapping(source = "businForm",target = "businForm",defaultValue = "02"),
@Mapping(source = "controlerLegalType",target = "legalType"),
@Mapping(source = "imgInfo",target = "imgInfo"),
@Mapping(source = "calcVal",target = "clearRate"),
@Mapping(target = "createTime",expression = "java( new java.util.Date() )"),
})
MerchantInfo convertMerchant(SmallMerchantVO smallMerchantVO);
@Mappings({
@Mapping(source = "regName", target = "mercName"),
@Mapping(source = "merchantName",target = "mercNickName"),
@Mapping(source = "merLegal",target = "linkman"),
@Mapping(source = "legalPhone",target = "telphone"),
@Mapping(source = "industries",target = "mccId"),
@Mapping(source = "address",target = "merArea"),
@Mapping(source = "employeeNum",target = "employeeNum",defaultValue = "1"),
@Mapping(source = "merLegal",target = "corpReptName"),
@Mapping(source = "legalCode",target = "corpReptId"),
@Mapping(source = "address",target = "province"),
@Mapping(source = "address",target = "city"),
@Mapping(source = "addressDetail",target = "corpAddr"),
@Mapping(source = "accType",target = "mercSettAcctType"),
@Mapping(source = "account",target = "mercSettAcct"),
@Mapping(source = "accName",target = "mercSettAcctNm"),
@Mapping(source = "bankCode",target = "mercSettBank"),
@Mapping(source = "bankName",target = "mercSettBankNm"),
@Mapping(source = "merType", target = "merMode"),
@Mapping(source = "capital",target = "capital",defaultValue = "10"),
@Mapping(source = "rxm",target = "merIdRxm"),
@Mapping(source = "ghm",target = "merIdGhm"),
@Mapping(source = "syt",target = "merSyt"),
@Mapping(source = "hjz",target = "merHjz"),
@Mapping(source = "mtz",target = "merMtz"),
@Mapping(source = "yyzz",target = "busiLicFileName"),
@Mapping(source = "merLic",target = "mercBusiLic"),
@Mapping(source = "licValidity",target = "licValiDate"),
@Mapping(source = "businForm",target = "businForm",defaultValue = "02"),
@Mapping(source = "controlerLegalType",target = "legalType"),
@Mapping(source = "imgInfo",target = "imgInfo"),
@Mapping(source = "calcVal",target = "clearRate"),
@Mapping(target = "createTime",expression = "java( new java.util.Date() )"),
})
MerchantInfo convertMerchant(BaseMerchantVO baseMerchantVO);
}
2.3 单元测试
package cn.itbeien.mapstruct.test;
import cn.itbeien.mapstruct.convert.MerchantConvert;
import cn.itbeien.mapstruct.entity.MerchantInfo;
import cn.itbeien.mapstruct.vo.MerchantInfoVO;
import cn.itbeien.mapstruct.vo.SmallMerchantVO;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
/**
* @author itbeien
* 项目网站:https://www.itbeien.cn
* 公众号:贝恩聊架构
* 全网同名,欢迎小伙伴们关注
* MapStruct 是一个对象属性映射工具,主要用于解决数据模型之间不通用的情况。用于对象与对象之间转换
* 对象属性值拷贝工具
* Copyright© 2024 itbeien
*/
@SpringBootTest
public class MapStructTest {
@Test
public void test(){
//vo和实体类属性名称不相同
SmallMerchantVO smallMerchantVO = new SmallMerchantVO();
smallMerchantVO.setRegName("华润万家");
smallMerchantVO.setMerchantName("华润万家");
smallMerchantVO.setAccName("itbeien");
smallMerchantVO.setAddress("中国深圳");
smallMerchantVO.setBusinForm("test");
MerchantInfo merchantInfo = MerchantConvert.INSTANCE.convertMerchant(smallMerchantVO);
System.out.println(merchantInfo);
//vo和实体类属性名称相同
MerchantInfoVO merchantInfoVO = new MerchantInfoVO();
merchantInfoVO.setMercNo("88888888");
merchantInfoVO.setMercName("万象城");
MerchantInfo merchantInfoOther = MerchantConvert.INSTANCE.convertMerchant(merchantInfoVO);
System.out.println(merchantInfoOther);
}
}

3 JavaBean中使用lombok
3.1 pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>cn.itbeien</groupId>
<artifactId>springboot3-labs-master</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>springboot-mapstruct-lombok</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
<annotationProcessorPaths>
<!-- 引入 lombok-processor -->
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok-version}</version>
</path>
<!-- 引入 mapstruct-processor -->
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${mapstruct-processor-version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</build>
</project>
3.2 mapstruct映射配置接口
mapstruct映射配置接口和2.2中的代码一样,这里直接展示使用了lombok注解的实体类,第2点中的方式没有使用Data注解自动生成get和set方法。
package cn.itbeien.mapstruct.lombok.entity;
import lombok.Data;
import java.math.BigDecimal;
import java.util.Date;
@Data
public class MerchantInfo {
private String mercNo;
private String mercName;
private String mercNickName;
private String publicKeyPath;
private String mercSignType;
private String mercPrivateKey;
private String status;
private String linkman;
private String telphone;
private String email;
private String address;
private String mccId;
private String merArea;
private String employeeNum;
private String contractNo;
private String contractPath;
private String mercBusiLic;
private String licValiDate;
private String busiLicFileName;
private String legalValidity;
private String corpReptName;
private String corpReptId;
private String postCode;
private String fixedPhone;
private String province;
private String city;
private String corpAddr;
private String oriPasswd;
private String passwd;
private String passwdFlag;
private Integer wrongCounts;
private Date lockedTime;
private String sendBillFlag;
private String mercSettAcctType;
private String mercSettAcct;
private String mercSettAcctNm;
private String mercSettBank;
private String mercSettBankNm;
private String mercSettBankPro;
private String mercSettBankCity;
private String clearCycle;
private String clearDate;
//费率
private String clearRate;
private String clearFlag;
private String agentNo;
private String manager;
private String servicePhone;
private Date createTime;
private String creator;
private Date updateTime;
private String updater;
private String mercPicsPath;
private String remark;
private BigDecimal creditAmt;
private String merMode;
private Integer capital;
private String busiLicPath;
private String merIdRxm;
private String merIdGhm;
private String merSyt;
private String merHjz;
private String merMtz;
private BigDecimal allowAmt;
private BigDecimal paySingleLimitAmt;
private BigDecimal payDailyLimitAmt;
private String payFlag;
private BigDecimal singleLimitAmt;
private BigDecimal dailyLimitAmt;
private String businForm;
private String approvers;
private String legalType;
/**
* 用于存储图片json格式
*/
private String imgInfo;
}
3.3 单元测试
单元测试代码整体都相同,自己查看代码。第一种方式和第二种方式区别只需要把pom.xml中的配置属性删除或新增即可,再一个就是JavaBean中有无Data注解

SpringBoot3专栏
01SpringBoot3专栏-SpringBoot3.4.0整合Mybatis-plus和Mybatis
02SpringBoot3.4.0结合Mybatis-plus实现动态数据源
跟着我学微服务系列
01跟着我学微服务,什么是微服务?微服务有哪些主流解决方案?
05SpringCloudAlibaba之图文搞懂微服务核心组件在企业级支付系统中的应用
06JDK17+SpringBoot3.4.0+Netty4.1.115搭建企业级支付系统POS网关
07JDK17+SpringCloud2023.0.3搭建企业级支付系统-预付卡支付交易微服务
08JDK17+Dubbo3.3.2搭建企业级支付系统-预付卡支付交易微服务
09JDK17+SpringBoot3.3.6+Netty4.1.115实现企业级支付系统POS网关签到功能
贝恩聊架构-项目实战地址
4 源码地址
贝恩聊架构-SpringBoot3专栏系列文章、资料和源代码会同步到以下地址,代码和资料每周都会同步更新
该仓库地址主要用于贝恩聊架构-SpringBoot3专栏、基于企业级支付系统,学习微服务整体技术栈
