mapstruct 实体转换及List转换,@Mapper注解转换
本文参考 https://blog.csdn.net/u012373815/article/details/88367456
主要是为了自己使用方便查询。 这些都是我平时用到了,大家有什么好方法或者有什么更多知识,希望大家不吝赐教
开发中,我们经常需要将PO转DTO、DTO转PO等一些实体间的转换。比较出名的有BeanUtil 和ModelMapper等,它们使用简单,但是在稍显复杂的业务场景下力不从心。MapStruct这个插件可以用来处理domin实体类与model类的属性映射,可配置性强。只需要定义一个 Mapper 接口,MapStruct 就会自动实现这个映射接口,避免了复杂繁琐的映射实现。MapStruct官网地址:http://mapstruct.org/
本文类型简单包含四方面:
(1)属性名称不对应
(2)list集合转换
(3)字段类型不对应
(4)多个来源实体转换成一个参数实体
引入依赖
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-jdk8</artifactId>
<version>1.1.0.Final</version>
</dependency>
需求
我们假设有学生student 类 需要转换成 用户 user 类,将学生信息存入用户信息库
此时Student 类内容如下:
public class Student {
private Integer id;
private String name;
private Integer age;
private String sex;//setters, getters, toString() 方法此处省略不写,但是实际开发需要写的哦
}
此时User 类内容如下
public class User {
private Integer id;
private String name;
private Integer age;
private String sex;//setters, getters, toString() 方法此处省略不写,但是实际开发需要写的哦 }
普通转换model
此时 Student 和 User 的属性名字都相同那么转换接口就是
import org.mapstruct.Mapper; @Mapper(componentModel = "spring")
public interface UserMapping { /**
* Student 转化为 User
* @param Student
* @return
*/
User studentToUser(Student student);
}
程序运行前要先编译 mvn clean compile , 从而mapstruct框架生成UserMappingImpl 实现类。
特殊转换model
(1)属性名称不对应,如果 User 和 Student 的属性名称不对应例如:
此时Student 类内容如下:
public class Student {
private Integer id;
private String sname;
private Integer age;
private String sex;
//setters, getters, toString() 方法此处省略不写,但是实际开发需要写的哦
}
此时User 类内容如下:
public class User {
private Integer id;
private String uname;
private Integer age;
private String sex;
//setters, getters, toString() 方法此处省略不写,但是实际开发需要写的哦
}
那么转换接口为
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Mappings; @Mapper(componentModel = "spring")
public interface UserMapping { /**
* Student 转化为 User
* @param Student
* @return
*/
@Mappings({
@Mapping(target = "uname", source = "sname")
// 多个属性不对应可以用 "," 隔开编写多个@Mapping
// ,@Mapping(target = "uname", source = "sname")
})
User studentToUser(Student student);
}
(2) 转换集合list
当user 和 student 都是集合形式list 时应当如下转换
转化 List<> 集合时必须有 实体转化,因为在实现中,List 转换是 for循环调用 实体转化的。所以当属性名不对应时,应该在 实体转化进行 @Mappings 的属性名映射配置,然后list的转换也会继承这和属性的映射。
例如 属性名相同
import org.mapstruct.Mapper; @Mapper(componentModel = "spring")
public interface UserMapping { /**
* Student 转化为 User
* @param Student
* @return
*/
User studentToUser(Student student); /**
* Students 转化为 Users
* @param Students
* @return
*/
List<User> studentsToUsers(List<Student> students);
属性名不同:
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Mappings; @Mapper(componentModel = "spring")
public interface UserMapping { /**
* Student 转化为 User
* @param Student
* @return
*/
@Mappings({
@Mapping(target = "uname", source = "sname")
// 多个属性不对应可以用 "," 隔开编写多个@Mapping
// ,@Mapping(target = "uname", source = "sname")
})
User studentToUser(Student student); /**
* 此时 studentsToUsers 的实现为循环调用 studentToUser 并继承了 studentToUser 的属性映射
* Students 转化为 Users
* @param Students
* @return
*/
List<User> studentsToUsers(List<Student> students);
}
展示 自动生成的 UserMappingImpl 实现(此类为 执行 mvn clean compile 后自动生成)
@Component
public class UserMappingImpl implements UserMapping {
@Override
public User studentToUser(student student) {
if ( student == null ) {
return null;
}
User user = new User();
User.setId(student.getId() );
User.setName(student.getName() );
// 如果配置了属性映射则为
//User.setUname(student.getSname() );
User.setSex(student.getSex() );
User.setAge(student.getAge() );
return user;
}
@Override
public List<User> studentsToUsers(List<student> students) {
if ( students == null ) {
return null;
}
List<User> list = new ArrayList<User>();
for ( student student : students ) {
list.add( studentToUser( student ) );
}
return list;
}
}
(3)字段类型不对应
字符串转时间,或者时间转字符串,都是用后面的dateFormat值为时间格式
@Mappings({
@Mapping(target = "createTime", source = "createTimeStr", dateFormat = "yyyy-MM-dd~hh:mm:ss")
// 多个属性不对应可以用 "," 隔开编写多个@Mapping
})
User studentToUser(Student student);
字段类型不对应,比如说user 类的sex字段类型改为boolean
此时User 类内容如下:
public class User {
private Integer id;
private String uname;
private Integer age;
private boolean sex;
//setters, getters, toString() 方法此处省略不写,但是实际开发需要写的哦
}
Mappings中qualifiedByName属性可以取由@Named声明的名称
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Mappings; @Mapper(componentModel = "spring")
public interface UserMapping { /**
* Student 转化为 User
* @param Student
* @return
*/
@Mappings({
@Mapping(target = "uname", source = "sname",qualifiedByName = "booleanToString")
// 多个属性不对应可以用 "," 隔开编写多个@Mapping // ,@Mapping(target = "uname", source = "sname")
})
User studentToUser(Student student); @Named("booleanToString")
default String booleanToString(boolean value){
if(value){
return "男";
}
return "女";
}
}
有的时候有一个额外的转换方法多个mapping类文件都要用到,所以肯定有写一个工具类,mapping引用外部的方法
public class Utils{
@Named("booleanToString")
default String booleanToString(boolean value){
if(value){
return "男";
}
return "女";
}
}
@Mapper(componentModel = "spring",uses=Utils.class)
public interface UserMapping {
/**
* Student 转化为 User
* @param Student
* @return
*/
@Mappings({
@Mapping(target = "uname", source = "sname",qualifiedByName = "booleanToString")
})
User studentToUser(Student student);
}
也可以直接使用expression
@Mappings({
@Mapping(target = "uname",expression = "java(booleanToString(student.getSname()))")
// 多个属性不对应可以用 "," 隔开编写多个@Mapping // ,@Mapping(target = "uname", source = "sname")
})
(4) 多个来源实体转换成一个参数实体
@Mappings({
@Mapping(target = "chartName", source = "chart.name"),
@Mapping(target = "title", source = "song.title"),
@Mapping(target = "artistName", source = "song.artist.name"),
@Mapping(target = "recordedAt", source = "song.artist.label.studio.name"),
@Mapping(target = "city", source = "song.artist.label.studio.city"),
@Mapping(target = "position", source = "position") })
ChartEntry map(Chart chart, Song song, Integer position);
(5)有一些参数不是来自传入参数,而是默认是一些外部的枚举类或者常量类数据,
就可以在mapper中声明要导入的外部枚举类或者常量类,
@Mapper(componentModel = "spring",
unmappedTargetPolicy = ReportingPolicy.IGNORE,
imports = {StringUtils.class,
UserConsts.class,
UserStatusEnum.class
})
@Mapping(target = "key",expression = "java( UserConsts.FULL_GIFT)"),
@Mapping(target = "status",expression = "java(UserStatusEnum.VALID_STATUS_NO.getCode())"),
mapstruct 实体转换及List转换,@Mapper注解转换的更多相关文章
- php如何遍历多维的stdClass Object 对象,php的转换成数组的函数只能转换外面一丛数组
php如何遍历多维的stdClass Object 对象,php的转换成数组的函数只能转换外面一丛数组 (2012-09-10 19:58:49) 标签: 杂谈 分类: 网页基础知识 php如何遍历多 ...
- piap.excel 微软 时间戳转换mssql sql server文件时间戳转换unix 导入mysql
piap.excel 微软 时间戳转换mssql sql server文件时间戳转换unix 导入mysql 需要不个mssql的sql文件导入mysql.他们的时间戳格式不同..ms用的是自定义的时 ...
- 使用sed,awk将love转换成LOVE,将CHINA转换成china
将love转换成LOVE,将CHINA转换成china echo "love CHINA" | sed -e 's/love/LOVE/' -e 's/CHINA/china/' ...
- 转换编码,将Unicode编码转换成可以浏览的utf-8编码
//转换编码,将Unicode编码转换成可以浏览的utf-8编码 public function unicodeDecode($name) { $pattern = '/([\w]+)|(\\\u([ ...
- 2017春 前端自动化(二) 页面自动刷新、sass与css转换的使用、pxToRem直观转换
2017春 前端自动化(二) 页面自动刷新.sass与css转换的使用.pxToRem直观转换 引言: 此文要演示:浏览器页面自动刷新:移动端px与rem的转换,简单直观化:使用sass自动生 ...
- MyBatis中的@Mapper注解及配套注解使用详解(上)
前言: 从mybatis3.4.0开始加入了@Mapper注解,目的就是为了不再写mapper映射文件(那个xml写的是真的蛋疼...).很恶心的一个事实是源码中并没有对于这个注解的详细解释 现在我们 ...
- MyBatis中的@Mapper注解 @Mappe与@MapperScan关系
从mybatis3.4.0开始加入了@Mapper注解,目的就是为了不再写mapper映射文件 现在项目中的配置 public interface DemoMapper{ int deleteByPr ...
- @Mapper注解在springboot中无法注入
问题① @Mapper注解报红无法注入 方法 在pom文件中添加依赖
- matlab学习笔记10_6 字符串与数值间的转换以及进制之间的转换
一起来学matlab-matlab学习笔记10 10_6 字符串与数值间的转换以及进制之间的转换 觉得有用的话,欢迎一起讨论相互学习~Follow Me 参考书籍 <matlab 程序设计与综合 ...
随机推荐
- STL初步学习(map)
3.map map作为一个映射,有两个参数,第一个参数作为关键值,第二个参数为对应的值,关键值是唯一的 在平时使用的数组中,也有点类似于映射的方法,例如a[10]=1,但其实我们的关键值和对应的值只能 ...
- Spring Boot + Vue + Shiro 实现前后端分离、权限控制
本文总结自实习中对项目的重构.原先项目采用Springboot+freemarker模版,开发过程中觉得前端逻辑写的实在恶心,后端Controller层还必须返回Freemarker模版的ModelA ...
- 在web开发中,为什么前端比后端更得到转行程序员的青睐?必看!
1.Web开发分类与区别 人们通常将Web分为前端和后端,前端相关的职位有前端设计师(UI/UE),前端开发工程师,后端相关的有后端开发工程师. 2.技术栈区别 看各大招聘网站上,公司对前端开发工程师 ...
- 洛谷P2566 [SCOI2009]围豆豆(状压dp+spfa)
题目传送门 题解 Σ(っ °Д °;)っ 前置知识 射线法:从一点向右(其实哪边都行)水平引一条射线,若射线与路径的交点为偶数,则点不被包含,若为奇数,则被包含.(但注意存在射线与路径重合的情况) 这 ...
- How many ways?? HDU - 2157 矩阵快速幂
题目描述 春天到了, HDU校园里开满了花, 姹紫嫣红, 非常美丽. 葱头是个爱花的人, 看着校花校草竞相开放, 漫步校园, 心情也变得舒畅. 为了多看看这迷人的校园, 葱头决定, 每次上课都走不同的 ...
- PE文件格式详解(一)
PE文件格式介绍(一) 0x00 前言 PE文件是portable File Format(可移植文件)的简写,我们比较熟悉的DLL和exe文件都是PE文件.了解PE文件格式有助于加深对操作系统的理解 ...
- HBuilder生成证书
一.安装jdk https://www.oracle.com/java/technologies/javase-downloads.html 二.打开CMD命令到JDK安装目录bin文件夹下 执行命令 ...
- day36 解决粘包问题
目录 一.tcp粘包问题出现的原因 二.解决粘包问题low的办法 三.egon式解决粘包问题 四.实现并发 1 tcp 2 udp 一.tcp粘包问题出现的原因 前引: tcp的客户端与服务端进行通信 ...
- MYSQL 之 JDBC(十二): 处理Blob
LOB,即Large Objects(大对象),是用来存储大量的二进制和文本数据的一种数据类型 LOB分为两种内省:内部LOB和外部LOB 内部LOB将数据以字节流的形式存储在数据库的内部.因而内部L ...
- 数据可视化基础专题(九):Matplotlib 基础(一)坐标相关
1.前言 图表要素如下图所示 # sphinx_gallery_thumbnail_number = 3 import matplotlib.pyplot as plt import numpy as ...