1、首先创建一个maven项目

2、导入相关的依赖

注意:lombok的版本

<?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>com.qbb.mapstruct</groupId>
<artifactId>mapstruct_demo</artifactId>
<version>1.0-SNAPSHOT</version> <properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<mapstruct.version>1.5.3.Final</mapstruct.version>
</properties> <dependencies>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>${mapstruct.version}</version>
</dependency> <dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${mapstruct.version}</version>
</dependency> <dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.10</version>
</dependency> <dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
</dependency>
</dependencies>
</project>

3、准备相关测试类

VO >>>>>>>

CarVO

package com.qbb.vo;

import lombok.Data;

/**
* @author QIUQIU&LL (个人博客:https://www.cnblogs.com/qbbit)
* @date 2022-11-14 21:47
* @tags 我爱的人在很远的地方, 我必须更加努力
*/
@Data
@Accessors(chain = true)
public class CarVO {
private Long id;
private String code;
private Double price;
private String totalPrice;
private String publishTime;
private String brand;
private Boolean hasPart;
private DriverVO driverVO;
}

DriverVO

package com.qbb.vo;

import lombok.Data;

/**
* @author QIUQIU&LL (个人博客:https://www.cnblogs.com/qbbit)
* @date 2022-11-14 21:49
* @tags 我爱的人在很远的地方, 我必须更加努力
*/
@Data
@Accessors(chain = true)
public class DriverVO {
private Long driverId;
private String fullName;
}

PartVO

package com.qbb.vo;

import lombok.Data;

/**
* @author QIUQIU&LL (个人博客:https://www.cnblogs.com/qbbit)
* @date 2022-11-14 21:54
* @tags 我爱的人在很远的地方, 我必须更加努力
*/
@Data
@Accessors(chain = true)
public class PartVO {
private Long partId;
private String partName;
}

DTO >>>>>>>

CarDTO

package com.qbb.dto;

import lombok.Data;

import java.time.LocalDateTime;
import java.util.List; /**
* @author QIUQIU&LL (个人博客:https://www.cnblogs.com/qbbit)
* @date 2022-11-14 21:43
* @tags 我爱的人在很远的地方, 我必须更加努力
*/
@Data
@Accessors(chain = true)
public class CarDTO {
private Long id;
private String code;
private double price;
private double totalPrice;
private LocalDateTime publishTime;
private String brand;
private List<PartDTO> partDTOList;
private DriverDTO driverDTO;
}

DriverDTO

package com.qbb.dto;

import lombok.Data;

/**
* @author QIUQIU&LL (个人博客:https://www.cnblogs.com/qbbit)
* @date 2022-11-14 21:46
* @tags 我爱的人在很远的地方, 我必须更加努力
*/
@Data
@Accessors(chain = true)
public class DriverDTO {
private Long id;
private String name;
}

PartDTO

package com.qbb.dto;

import lombok.Data;

/**
* @author QIUQIU&LL (个人博客:https://www.cnblogs.com/qbbit)
* @date 2022-11-14 21:46
* @tags 我爱的人在很远的地方, 我必须更加努力
*/
@Data
@Accessors(chain = true)
public class PartDTO { private Long partId;
private String partName;
}

4、案例

(1) 默认映射@Mapper

先创建一个convert

package com.qbb.convert;

import com.qbb.dto.CarDTO;
import com.qbb.vo.CarVO;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers; /**
* @author QIUQIU&LL (个人博客:https://www.cnblogs.com/qbbit)
* @date 2022-11-14 21:59
* @tags 我爱的人在很远的地方, 我必须更加努力
*/
@Mapper
public interface CarConvert {
//
CarConvert CONVERT = Mappers.getMapper(CarConvert.class); /**
* dto ---> vo
*
* @param carDTO
* @return
*/
CarVO dto2vo(CarDTO carDTO);
}

CarTest测试

package com.qbb;

import com.qbb.convert.CarConvert;
import com.qbb.dto.CarDTO;
import com.qbb.dto.DriverDTO;
import com.qbb.dto.PartDTO;
import com.qbb.vo.CarVO;
import org.junit.Test; import java.time.LocalDateTime;
import java.util.Arrays; /**
* @author QIUQIU&LL (个人博客:https://www.cnblogs.com/qbbit)
* @date 2022-11-14 22:05
* @tags 我爱的人在很远的地方, 我必须更加努力
*/
public class CarTest {
@Test
public void test01() {
CarDTO carDTO = new CarDTO();
carDTO.setId(999L);
carDTO.setCode("123321");
carDTO.setPrice(199999.999D);
carDTO.setTotalPrice(999999.99D);
carDTO.setPublishTime(LocalDateTime.now());
carDTO.setBrand("奔驰");
carDTO.setPartDTOList(Arrays.asList(new PartDTO().setPartId(1L).setPartName("零件1"),
new PartDTO().setPartId(2L).setPartName("零件2")));
carDTO.setDriverDTO(new DriverDTO().setId(1L).setName("张三")); CarVO carVO = CarConvert.CONVERT.dto2vo(carDTO);
System.out.println("carVO = " + carVO);
}
}

结果

默认映射规则
- 同类型同名的属性自动映射
- mapstruct会进行自动类型转换
- 8中基本类型和对应的包装类之间
- 8中基本类型(包装类)和String之间
- 日期和String之间

(2) @Mappings、@Mapping

在CarDTO和CarVO中加入几个测试属性

CarDTO

private String color;
private Boolean status;

CarVO

private String color;
private Integer stat;

测试

package com.qbb.convert;

import com.qbb.dto.CarDTO;
import com.qbb.dto.DriverDTO;
import com.qbb.vo.CarVO;
import com.qbb.vo.DriverVO;
import org.mapstruct.*;
import org.mapstruct.factory.Mappers; import java.util.List; /**
* @author QIUQIU&LL (个人博客:https://www.cnblogs.com/qbbit)
* @date 2022-11-14 21:59
* @tags 我爱的人在很远的地方, 我必须更加努力
*/
@Mapper
public interface CarConvert {
//
CarConvert CONVERT = Mappers.getMapper(CarConvert.class); /**
* dto ---> vo
*
* @param carDTO
* @return
*/
@Mappings({
@Mapping(source = "totalPrice", target = "totalPrice", numberFormat = "#.0"), // 指定格式化规则
@Mapping(source = "publishTime", target = "publishTime", dateFormat = "yyyy-MM-dd HH:mm:ss"), // 指定日期格式化
@Mapping(target = "color", ignore = true), // 忽略某个字段映射
//@Mapping(source = "brand",target = "brandName"), // 字段名不一致映射
@Mapping(source = "driverDTO", target = "driverVO"), // 引用对象的映射 使用到下面的方法 driverDTO2DriverVO
@Mapping(source = "status", target = "stat", qualifiedByName = "boolean2Integer") // 自定义映射
})
CarVO dto2vo(CarDTO carDTO); /**
* DriverDTO ---> DriverVO
*
* @param driverDTO
* @return
*/
@Mapping(source = "id", target = "driverId")
@Mapping(source = "name", target = "fullName")
DriverVO driverDTO2DriverVO(DriverDTO driverDTO); /**
* 自定义映射
*
* @return
*/
@Named("boolean2Integer")
default Integer boolean2Integer(Boolean bool) {
if (bool) return 1;
return 0;
} /**
* 自定义映射2
*/
@AfterMapping // @AfterMapping表示自动转换方法完成后,自动调用本方法
default void dto2voAfter(CarDTO carDTO, @MappingTarget CarVO carVO) { // @MappingTarget表示CarVO是已经赋值了的
if (carDTO.getStatus()) carVO.setStat(1);
else carVO.setStat(0);
} /**
* 批量转换
*
* @param carDTOS
* @return
*/
@BeanMapping(ignoreByDefault = true) // 忽略默认映射,只映射@Mapping指定的映射
@Mapping(source = "id", target = "id")
List<CarVO> lsitDTO2ListVO(List<CarDTO> carDTOS);
}

5、@MappingTarget用法

我们使用@mapping时,转换器给帮我们new一个对象,这样的话源对象的属性会丢失。。。这就很尴尬~所以MapStruct提供了@MappingTarget注解解决这个问题

// 使用@mapping时,转换器给帮我们new一个对象
@Override
public DeptVO deptToDeptVO(Dept dept) {
if ( dept == null ) {
return null;
}
// 尴尬点~~~~
DeptVO deptVO = new DeptVO(); deptVO.setDeptId( dept.getDeptId() );
deptVO.setDeptName( dept.getDeptName() );
deptVO.setStaff( dept.getStaff() );
deptVO.setTel( dept.getTel() );
deptVO.setDeleted( dept.getDeleted() );
deptVO.setVersion( dept.getVersion() );
deptVO.setGmtCreate( dept.getGmtCreate() );
deptVO.setGmtModified( dept.getGmtModified() ); return deptVO;
}

例如:

我想把部门dept中的部门名和部门id等等属性转换到UserVO中

/**
* 追加更新属性
* 可以有返回值也可以无返回值
*
* @param userVO 源对象
* @param dept
*/
UserVO appendAttrToUserVO(Dept dept, @MappingTarget UserVO userVO);

转换器生成的代码

@Override
public UserVO appendAttrToUserVO(Dept dept, UserVO userVO) {
if ( dept == null ) {
return userVO;
} userVO.setDeptId( dept.getDeptId() );
userVO.setDeleted( dept.getDeleted() );
userVO.setVersion( dept.getVersion() );
userVO.setGmtCreate( dept.getGmtCreate() );
userVO.setGmtModified( dept.getGmtModified() );
userVO.setDeptName( dept.getDeptName() );
userVO.setStaff( dept.getStaff() );
userVO.setTel( dept.getTel() ); return userVO;
}

结果:

{
"code": 200,
"msg": "操作成功",
"data": {
"userId": 1,
"userName": "1665646693248",
"age": 1,
"email": "ab@c.c",
"deptId": 10,
"deleted": false,
"version": 4,
"gmtCreate": "2020-10-30 03:48:19",
"gmtModified": "2022-10-13 07:36:20",
"deptName": "1665646580778",
"staff": 20,
"tel": "88886666"
}
}

注意:@MappingTarget注解没有任何属性,source bean(源对象) 和 target bean(目标对象) 的属性必须一致,才能映射,否则不会映射,但也不报错!!! 当然如果,可以自定义方法转换,参考上面的

6、与Spring整合

与Spring整合非常容易,主需要在注解中加入一个属性,其实就是给他帮我们生成的实现类上加入了一个@Component,所以我们后面就可以使用@Autowired @Resource注入即可

@Mapper(componentModel = "spring")

代码仓库:https://gitee.com/Ybbit/map-struct.git

MapStruct使用的更多相关文章

  1. VO和DO转换(四) MapStruct

    VO和DO转换(一) 工具汇总 VO和DO转换(二) BeanUtils VO和DO转换(三) Dozer VO和DO转换(四) MapStruct MapStruct

  2. mapstruct与lombok结合使用

    当mapstruct与lombok想结合使用的时候,出现了生成的MapperImpl里方法,没有对实体进行转换的情况. 解决方案: <plugin> <groupId>org. ...

  3. MapStruct

    一.Object mapping 的技术分类: 运行期 反射调用set/get 或者是直接对成员变量赋值 . 该方式通过invoke执行赋值,实现时一般会采用beanutil, Javassist等开 ...

  4. spring boot 之使用mapstruct

    最近在阅读swagger源码,当看到 springfox.documentation.swagger2.mappers.ModelMapper 类时,无意中看到该类上面使用的 org.mapstruc ...

  5. java之mapstruct的应用

    一.MapStruct是一个代码生成器,简化了不同的Java Bean之间映射的处理,所以映射指的就是从一个实体变化成一个实体.例如我们在实际开发中,DAO层的实体和一些数据传输对象(DTO),大部分 ...

  6. 16、SpringBoot------整合MapStruct

    开发工具:STS 前言: 前端提交往后端的数据,一部分是不需要存入数据库当中的: 后端从数据库中取出的数据,一部分是不可以交给用户的: 那么,po面向的是DB,vo面向的是客户端, mapstruct ...

  7. 对象拷贝 - 优雅的解决方案 Mapstruct

    MapStruct GitHub 访问地址 : https://github.com/mapstruct/mapstruct/ 使用例子 : https://github.com/mapstruct/ ...

  8. Java编码辅助工具:Mapstruct—— Java对象转换框架

    项目开发中,业务分层会涉及不同类型的Bean之间需要相互转换,如PO与DTO之间,PO与VO之间等.手动编码setter/getter各个对应属性,会显得臃肿繁琐.通过Mapstruct框架可简单方便 ...

  9. mapStruct笔记

    背景 mapStruct 是一个方便对象转换的工具,类似的工具还有 Dozer, BeanUtils. 实现 mapStruct的核心是在编译期生成基于转换规则的 Impl 文件,运行时直接调用 Im ...

  10. 推荐一个 Java 实体映射工具 MapStruct

    声明: 1.DO(业务实体对象),DTO(数据传输对象). 2.我的代码中用到了 Lombok ,不了解的可以自行了解一下,了解的忽略这条就好. 在一个成熟的工程中,尤其是现在的分布式系统中,应用与应 ...

随机推荐

  1. C++ 算法竞赛、02 周赛篇 | AcWing 第2场周赛

    AcWing 第2场周赛 竞赛 - AcWing 3626 三元一次方程 AcWing 3626. 三元一次方程 - AcWing 两层循环 #include <iostream> usi ...

  2. ionic4请求skynet服务器的资源跨域问题

    最近在做一个后台接口, 顺便用ionic4写了个简单的管理后台, 本来skynet管理后台监听的端口是6666, 但是发现chrome默认对一些接口不友善, 虽然可以通过设置启动参数来解决, 但是还是 ...

  3. 【RocketMQ】DLedger模式下的选主流程分析

    RocketMQ 4.5版本之前,可以采用主从架构进行集群部署,但是如果master节点挂掉,不能自动在集群中选举出新的Master节点,需要人工介入,在4.5版本之后提供了DLedger模式,使用R ...

  4. DESTOON做中英双语言(多语言)切换版本具体详解

    第一次发原创好激动,该注意点什么? 在开发过程中用户有许多要求,比如这个多语言切换就是一个需求. 首先讲解一下DESTOON(DT)后台系统如何做这个中英.甚至多语言切换的这个功能. DT本身不自带多 ...

  5. 【最佳实践】高可用mongodb集群(1分片+3副本):规划及部署

    结合我们的生产需求,本次详细整理了最新版本 MonogoDB 7.0 集群的规划及部署过程,具有较大的参考价值,基本可照搬使用. 适应数据规模为T级的场景,由于设计了分片支撑,后续如有大数据量需求,可 ...

  6. 使用 Kubernetes 简化平台工程

    平台工程在现代应用程序开发和部署中发挥的作用至关重要.随着软件应用程序变得越来越复杂和分散,对稳健且可扩展的基础设施的需求变得越来越重要.这就是平台工程的作用所在,它是支持整个软件开发生命周期的支柱. ...

  7. go使用snmp库查询mib数据

    转载请注明出处: OID(Object Identifier)是一种用于标识和唯一命名管理信息库中的对象的标准方式.给定一个OID,可以确定特定的管理信息库对象,并对其进行操作. go语言使用snmp ...

  8. 利用OpenXML获取Excel单元格背景色

    利用OpenXML获取Excel单元格背景色 最近项目上遇到了关于Excel获取处理的问题,关于Excel单元格背景色的获取,水的文章都大同小异,都没注意到Excel单元格背景色是怎么赋值,这会导致出 ...

  9. 从基础到实践,回顾Elasticsearch 向量检索发展史

    本文分享自华为云社区<Elasticsearch向量检索的演进与变革:从基础到应用>,作者: 汀丶. 1.引言 向量检索已经成为现代搜索和推荐系统的核心组件. 通过将复杂的对象(例如文本. ...

  10. logback java动态配置【动态修改日志级别,动态修改appender】(转)

    logback 动态配置 写在前面在做java日志之前,强烈建议大家读一下这篇java日志的前世今生,对理清java日志框架很有帮助!1奉上地址: 一个著名的日志系统是怎么设计出来的 然后说一下,为啥 ...