每天坚持写一篇原创文章。

使用过MapStruct之后,再也没用过BeanCopy来复制对象了。确实是非常好用的工具库。



MapStruct是一个代码生成器,简化了不同的Java Bean之间映射的处理,所以映射指的就是从一个实体变化成一个实体。例如我们在实际开发中,DAO层的实体和一些数据传输对象(DTO),大部分属性都是相同的,只有少部分的不同,通过mapStruct,可以让不同实体之间的转换变的简单。我们只需要按照约定的方式进行配置即可。

大家的命名都不一样,我个人是习惯把数据库的DO对象叫Entity实体。

返回前端的叫VO。

把Entity复制到VO并做一些操作或者转换,再返回前端,都会用到。

安装

1、引用

唯一需要注意的就是如果配合Lombok,需要在编译源码的插件上做好配置。

<properties>
<mapstruct.version>1.3.0.Final</mapstruct.version>
</properties> <!-- MapStruct核心,包含了一些必要的注解-->
<dependencies>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>${mapstruct.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven.compiler-plugin.version}</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
<compilerVersion>${java.version}</compilerVersion>
<fork>true</fork>
<encoding>${project.build.sourceEncoding}</encoding>
<verbose>true</verbose>
<annotationProcessorPaths>
<!-- 同时用Lombok,需要将Lombok放前面 -->
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</path>
<!-- MapStruct编译,注解处理器,根据注解自动生成Mapper的实现 -->
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${mapstruct.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</build>

2、定义转换接口

@Mapper
public interface OrderConvertor { OrderConvertor INSTANCE = Mappers.getMapper(OrderConvertor.class); @Mapping(source = "student.birthday", target = "birthday", dateFormat = "yyyy-MM-dd HH:mm:ss") // 指定时间格式
@Mapping(target = "name", source = "student.name", defaultValue = "张三") //默认值
OrderVo toVo(OrderEntity order);
}

target表示目标属性名,source表示源属性名,一般在目标属性和源属性不同时使用,相同的属性名会自动进行映射。

MapStruct会自动生成对应接口的实现,并自动完成属性映射关系,List会自动进行批量处理。

3、使用时

@Service
public class OrderService {
public List<OrderVo> getOrderList() {
// 获取数据库数据
List<OrderEntity> result = selectOrderList();
// 参数转换
return OrderConvertor.INSTANCE.toVo(result);
}
}

下面是我常用的一些功能记录

1、添加为Spring的Component组件

@Mapper(componentModel = "spring")

2、List转换为String

类注解加上引用

@Mapper(imports = {Collectors.class, TelegramGroupEntity.class})

代码里面:使用表达式,转换为字符串

@Mapping(target = "groupStr", expression = "java(source.getBindGroups()!= null? source.getBindGroups().stream().map(TelegramGroupEntity::getName).collect(Collectors.joining(\", \")) : null)")
AcceptanceBankVo convert(AcceptanceBankEntity source);

直接转换List为换行的String

@Mapping(target = "groupStr", expression = "java(source.getBindGroups()!= null? source.getBindGroups().stream().map(TelegramGroupEntity::getName).collect(Collectors.joining(\"\\n\")) : null)")

直接调用方法

@Mapper(imports = {Collectors.class, TelegramGroupEntity.class, IndiaDateUtil.class})
public interface TransferBankConvert {
TransferBankConvert INSTANCE = Mappers.getMapper(TransferBankConvert.class); @Mapping(target = "timeAgo", expression = "java(source.getLastActiveTime()!= null? IndiaDateUtil.getTimeAgo(source.getLastActiveTime(),\"Asia/Kolkata\") : null)")
TransferBankVo convert(TransferBankEntity source);
}

3、获取时间

@Mapping(target = "recordTime",expression = "java(new java.util.Date())")

4、空检查

@Mapper(nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS)

5、枚举映射String和string到枚举

int转枚举的value

@Mapper(imports = {AccptanceRoleTypeEnum.class}) // 加到类上引用进来

@Mapping(target = "roleText", expression = "java(AccptanceRoleTypeEnum.getItemValue(source.getRole()))")

枚举上加上:

/**
* 根据Value取描述
* @param value
* @return
*/
public static String getItemValue(Integer value) {
AccptanceRoleTypeEnum match = Stream.of(values()).filter(item -> item.value.equals(value)).findAny().orElse(null);
return match == null ? null : match.getDesc();
}

6、Fill同对象填充新对象,把source填充到target里面,和以前的beancopy一样的。

@BeanMapping(nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE,
nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS)
@Mappings({
@Mapping(target = "id", ignore = true),
@Mapping(target = "createTime", ignore = true),
@Mapping(target = "updateTime", ignore = true)
})
void fill(TelegramGroupRoleEntity source, @MappingTarget TelegramGroupRoleEntity target);

要忽略空值填充

@BeanMapping(nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE)
void update(DTO dto, @MappingTarget Bean bean);

7、Map提取,还是用表达式最简单

@Mappings({
@Mapping(expression = "java(mapConfig.getOrDefault(\"INPAY_RATES\",""))", target = "inpayRates"),
@Mapping(expression = "java(mapConfig.getOrDefault(\"AUTO_CREDIT\",""))", target = "autoCredit")
})
TelegramGroupWithConfigVo convert(TelegramGroupEntity entity);

8、空值判断

@Mapping(target = "targetField", expression = "java( sourceField == null || sourceField.isEmpty() ? null : sourceField )") 来将空字符串映射为 null

更多内容请关注我的公众号:青塬科技。

MapStruct的一些常规用法的更多相关文章

  1. GridView的常规用法

    GridView控件在Asp.net中相当常用,以下是控件的解释,有些是常用的,有些是偶尔用到的,查找.使用.记录,仅此而已.(最后附带DropDownList控件) ASP.NET中GridView ...

  2. mapreduce的cleanUp和setUp的特殊用法(TopN问题)和常规用法

    一:特殊用法 我们上来不讲普通用法,普通用法放到最后.我们来谈一谈特殊用法,了解这一用法,让你的mapreduce编程能力提高一个档次,毫不夸张!!!扯淡了,让我们进入正题: 我们知道reduce和m ...

  3. 【python】-matplotlib.pylab常规用法

    目的: 了解matplotlib.pylab常规用法 示例 import matplotlib.pylab as pl x = range(10) y = [i * i for i in x] pl. ...

  4. MarkDown的常规用法

    MarkDown的常规用法 标题 # 一级标题 ## 二级标题 ... ###### 六级标题 列表 第二级 - 和 空格 + 和 空额 * 和 空格 第三级 代码块 多行代码块 3个` 回车 单行代 ...

  5. C# 当中 LINQ 的常规用法(Lambda 方式)

    仅以本篇博文记录 LINQ 相关操作的基本知识,原型参考自 MSDN 相关知识,中间加以自己的理解与 DEMO. 1. IEnuemrable<T>.Select() Select 方法比 ...

  6. Vuex 常规用法

    背景 很多时候我们已经熟悉了框架的运用,但是有时候就是忘了怎么用 所以这里想记下大部分的框架使用方法,方便使用的时候拷贝 一.安装 npm 方式 npm install vuex --save yar ...

  7. iOS -Swift 3.0 -String(字符串常规用法)

    // // ViewController.swift // Swift-String // // Created by luorende on 16/9/10. // Copyright © 2016 ...

  8. 关于strong、copy、weak、assign的常规用法

    strong   对于普通的OC对象都是使用strong copy     对于 NSString,Block weak    用于OC对象,1.当出现循环强引用的时候,必须要保证一端是weak, 2 ...

  9. SimpleDateFormat 常规用法

    public class SimpleDateFormat extends DateFormat SimpleDateFormat 是一个以国别敏感的方式格式化和分析数据的具体类. 它允许格式化 (d ...

  10. UITabbar的一些常规用法(总结)

    往往系统自带的UITabbar 不能满足我们的样式或者颜色设计,所以需要调整UITabbar. 1.自定义UITabbar,也是我学到的第一种方式(简单暴力). 先记录一下思路: 首先,隐藏系统自带的 ...

随机推荐

  1. 【K哥爬虫普法】大众点评VS百度地图,论“数据权属”对爬虫开发的罪与罚!

    我国目前并未出台专门针对网络爬虫技术的法律规范,但在司法实践中,相关判决已屡见不鲜,K哥特设了"K哥爬虫普法"专栏,本栏目通过对真实案例的分析,旨在提高广大爬虫工程师的法律意识,知 ...

  2. P9110 [PA2020] Samochody dostawcze

    题目简述 有 \(n\) 个点,这些点分为两种类型.第一种,点在 \((x,0)\) 的位置.这些点从 \(t_i\) 的时刻开始向北走.第二种,点在 \((0,y)\) 的位置.这些点从 \(t_i ...

  3. 有道云笔记之备选方案Obsidian和Notion

    有道云笔记限制登录设备 在商业项目中一般都会有plana.planb,对于云笔记,我也在寻找planb,有道云笔记在国内市场已经占据了很大的份额. 同类型中的就不再去挑选了,我觉得商业软件,迟早也会走 ...

  4. TienChin 渠道管理-渠道类型

    在上一篇文章当中,表里面有一个渠道类型,我们这节主要是将这个渠道类型创建好,首先我们来看看字典表. sys_dict_type 表: 字段名 数据类型 注释 dict_id bigint 字典主键 d ...

  5. 【三】分布式训练---单机多卡与多机多卡组网(飞桨paddle2.0+)更加推荐spawn方式!

    1. 单机多卡启动并行训练 飞桨2.0增加paddle.distributed.spawn函数来启动单机多卡训练,同时原有的paddle.distributed.launch的方式依然保留. padd ...

  6. Python 字符串与字节数组转换

    整数之间的进制转换: 10进制转16进制: hex(16) ==> 0x10 16进制转10进制: int('0x10', 16) ==> 16 类似的还有oct(), bin() 字符串 ...

  7. C#合成图片显示不全

    现象 前段时间用C#写了一个小工具,主要功能是随机读取图片并合成一张长图.最近在使用的时候发现个问题,原图片宽度是1080,合成后的图片宽度也是1080,但是合成后的图片没有显示全,就像下面这样 原图 ...

  8. Apache和Nginx是什么?|Nginx和Reactor是什么?|网路IO的本质|阻塞队列|异步非阻塞IO

    前言 那么这里博主先安利一些干货满满的专栏了! 首先是博主的高质量博客的汇总,这个专栏里面的博客,都是博主最最用心写的一部分,干货满满,希望对大家有帮助. 高质量干货博客汇总https://blog. ...

  9. Leetcode刷题第二天-贪心

    655:非递减数列 链接:665. 非递减数列 - 力扣(LeetCode) 直接找最大最小值进行替换不行,[1,5,4,6,7,8,9]最大最小值所处位置可能是非递减数列 如果nums[i]> ...

  10. JS leetcode 旋转数组 题解分析

    壹 ❀ 引 今天来做一道同样简单,但是挺有趣的题,题目来自leetcode189. 旋转数组,题目描述如下: 给定一个数组,将数组中的元素向右移动 k 个位置,其中 k 是非负数. 示例 1: 输入: ...