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

Java实体对象转换利器MapStruct详解

概述

现在的JAVA项目多数采用分层结构,参考《阿里巴巴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 :数据查询对象,各层接收上层的查询请求。注意超过 2 个参数的查询封装,禁止
使用 Map 类来传输。
那么,进行就需要这些 对象的转换

例如将UserDo转换为UserVo就很普遍,如下所示:

public class UserDo{private String name;private Integer age;
}

转换为:

public class UserVo {private String name;private Integer age;
}

手动进行对象的转换,虽然执行性能很高,但是开发效率非常低下,且可能会存在错漏的情况。因此,我们会选择借助框架或是工具来实现对象的转换,之前常用BeanUtils(有多种可选,性能对比网上找找),现在多了一个选择就是MapStruct。

MapStruct

简介

MapStruct 是一个JSR 269 的 Java 注解处理器,是它是基于注解的,而且是编译时APT(annotation processor tool)。不像其他APT是运行时,例如Spring里面的注解处理方式,是在运行时通过反射的方式处理的。

使用

maven配置

    <properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><maven.compiler.source>1.8</maven.compiler.source><maven.compiler.target>1.8</maven.compiler.target><mapstruct.version>1.5.3.Final</mapstruct.version><lombok.version>1.18.20</lombok.version><lombok-mapstruct-binding.version>0.2.0</lombok-mapstruct-binding.version></properties><dependencies><dependency><groupId>org.mapstruct</groupId><artifactId>mapstruct</artifactId><version>${mapstruct.version}</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>${lombok.version}</version><scope>provided</scope></dependency></dependencies><build><pluginManagement><plugins>...<plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><version>3.8.1</version><configuration><source>${maven.compiler.source}</source><target>${maven.compiler.target}</target><annotationProcessorPaths><path><groupId>org.mapstruct</groupId><artifactId>mapstruct-processor</artifactId><version>${mapstruct.version}</version></path><path><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>${lombok.version}</version></path><path><groupId>org.projectlombok</groupId><artifactId>lombok-mapstruct-binding</artifactId><version>${lombok-mapstruct-binding.version}</version></path></annotationProcessorPaths></configuration></plugin></plugins></pluginManagement></build>

应用

假设我们有如下两个需要转换的类:

@Data
public class UserDo {private String name;private String gender;private Double height;private Date birthday;private Address address;private String girlName;private String girlDes;
}@Data
public class UserVo {private String name;private String gender;private String height;private String bornDay;private AddressDto address;private GirlFriendDto girlFriend;
}

第一步: 定义一个interface,使用 @Mapper 标记。

第二步:构建一个实例属性用于访问里面的方法。

@Mapper
public interface UserConvetor {UserConvetor INSTANCE = Mappers.getMapper(UserConvetor.class);
}

 第三步:提供转换方法申明,必要时使用@Mapping注解

@Mapper
public interface UserConvetor {UserConvetor INSTANCE = Mappers.getMapper(UserConvetor.class);@Mapping(target = "bornDay", source = "birthday")UserVo toUserVo(UserDo userDo);
}

自定义映射

MapStruc默认会将两个bean的名称相同的属性进行映射,如果source与target的属性名称不一致则需要借助@Mapping注解。编译程序后就会在\target\generated-sources\annotations下产生UserConvetorImpl实现类了。

 第四步:代码中使用UserConvetor转换类

public void runConvetor(){UserDo userDo = new UserDo();userDo.setName("张三");...UserVo userVo= UserConvetor.INSTANCE.toUserVo(userDo);log.info("vo: {}", userVo);
}

忽略映射

如果不想给UserDobirthday赋值可以忽略它。

@Mapping(target = "bornDay", ignore = true)
UserVo toUserVo(UserDo userDo);

设置默认值

如果想实现在source值为null时给一个默认值也是可以了。

@Mapping(target = "gender", defaultValue = "man")
UserVo toUserVo(UserDo userDo);

设置常量

@Mapping(target = "height", constant = "175")

数据类型转换

日期类型转换

@Mapping(target = "bornDay", source = "birthday", dateFormat = "yyyy-MM-dd HH:mm:ss")
UserVo toUserVo(UserDo userDo);

小数点位数转换 

@Mapping(target = "height", source = "height" ,numberFormat = "#.00")

表达式 

大写转换

@Mapping(target = "name", expression = "java(programer.getName().toUpperCase())")

 方法调用

@Mapping(target = "name", expression = "java(nameToUp(userDo))")
UserVo toUserVo(UserDo userDo);default String nameToUp(UserDo userDo){return Optional.ofNullable(userDo).filter(Objects::nonNull).map(u->u.getName()).orElse(null).toUpperCase();
}

 

嵌套映射

我们经常会遇到bean里面套着bean的映射。

{"name":"shusheng007","address":{"country":"China","city":"TianJin"}
}

对于这样的映射,我们只需要在mapper中提供一个嵌套bean的转换关系即可。

@Mapping(target = "address", source = "address")
UserVo toUserVo(UserDo userDo);
//嵌套bean的转换关系
AddressDto toAddressDto(Address addr);

集合映射

只需要提供集合元素类型的映射即可。

AddressDto toAddressDto(Address addr);List<AddressDto> toAddressList(List<Address> addrList);

多个数据对象

@Mapping(target = "name", source = "programer.name")
@Mapping(target = "girlFriendName", source = "girl.name")
UserVo toUserVo(UserDo userDo, Gir girl);

 其他还有外部引用、切面操作在此就不一一列举。

IDE 插件

MapStruct 提供了 IDEA MapStruct Support 插件,让我们在 IDEA 中,可以更愉快的使用 MapStruct!


http://www.mrgr.cn/news/44567.html

相关文章:

  • Maven 入门详解
  • linux 重置root密码
  • 【英语】考研英语语法体系
  • 【大语言模型-论文精读】用于医疗领域摘要任务的大型语言模型评估综述
  • LSTM模型实现电力数据预测
  • 微信小程序开发问题记录
  • 复现文章:R语言复现文章画图
  • 数据仓库拉链表
  • 【PostgreSQL】PG数据库表“膨胀”粗浅学习
  • 【Spring】“请求“ 之后端传参重命名,传递数组、集合,@PathVariable,@RequestPart
  • localhost与127.0.0.1傻傻分不清楚,区别详解来了
  • HarmonyOS与Android在设计理念、系统架构、性能优化等方面全面对比
  • 插入数据库报错 ER_DUP_ENTRY
  • 中国喀斯特地貌分布shp格式数据
  • Acwing 数位统计DP
  • Linux的发展历史与环境
  • 【深度学习基础模型】图神经网络(Graph Neural Networks, GNNs)详细理解并附实现代码。
  • 股市突然暴涨,需要保持理性
  • 18732 最短路问题
  • Oracle 实时表空间使用率和最大表空间使用率区别