首页>>后端>>java->优雅的对象转换

优雅的对象转换

时间:2023-11-29 本站 点击:60

MapStruct简单介绍

MapStruct 是一个属性映射工具,只需要定义一个 Mapper 接口,MapStruct 就会自动实现这个映射接口,避免了复杂繁琐的映射实现。

在一个Java工程中会涉及到多种对象,po、vo、dto、entity、do、domain这些定义的对象运用在不同的场景模块中,这种对象与对象之间的互相转换,就需要有一个专门用来解决转换问题的工具。以往的方式要么是自己写转换器,要么是用Apache或Spring的BeanUtils来实现转换。无论哪种方式都存在明显的缺点,比如手写转换器既浪费时间, 而且在添加新的字段的时候也要进行方法的修改;而无论是 BeanUtils, BeanCopier 等都是使用反射来实现,效率低下并且仅支持属性名一致时的转换。

MapSturct 是一个生成类型安全, 高性能且无依赖的 JavaBean 映射代码的注解处理器。作为一个工具类,相比于手写,其具有便捷,不容易出错的特点。

MapStruct的使用

引入依赖

maven工程需要在pom文件中引入以下依赖

<properties><mapstruct.version>1.3.0.Final</mapStruct.version></properties><dependencies><dependency><groupId>org.mapstruct</groupId><artifactId>mapstruct-jdk8</artifactId><version>${mapstruct.version}</version></dependency><dependency><groupId>org.mapstruct</groupId><artifactId>mapstruct-processor</artifactId><version>${mapstruct.version}</version></dependency></dependencies>

基本使用

定义数据实体

@Data@AllArgsConstructor@TableName("user")publicclassUser{@TableId(value="id",type=IdType.AUTO)privateLongid;@TableField("user_name")privateStringuserName;@TableField("gender")privateIntegergender;@TableField("age")privateIntegerage;@TableField("flag")privateIntegerflag;}

定义转换实体

@DatapublicclassUserDto{privateLongid;privateStringname;privateStringgender;privateIntegerage;}

编写转换接口

@MapperpublicinterfaceUserMapStruct{UserMapStructINSTANCE=Mappers.getMapper(UserMapStruct.class);/***单一对象的转换*这里模拟两种情况:1、属性名不一致2、使用表达式将实体类的性别int类型转成枚举中定义的性别的String类型释义*/@Mapping(source="userName",target="name")@Mapping(target="gender",expression="java(com.rameo.mapstruct.GenderEnum.desc(user.getGender()))")//支持表达式UserDtouserToDto(Useruser);/***对象集合的转换*/List<UserDto>userToDtoList(List<User>userList);}

编写测试方法

@RunWith(SpringRunner.class)@SpringBootTestpublicclassUserMapStructTest{privateUseruser;@Beforepublicvoidbefore(){user=newUser(1L,"sw","shenzhen",11,1);}@Testpublicvoidtest(){UserDtouserDto=UserMapStruct.INSTANCE.userToDto(user);Assert.assertNotNull(userDto);Assert.assertEquals(userDto.getId(),1);Assert.assertEquals(userDto.getName(),"sw");Assert.assertEquals(userDto.getCity(),"shenzhen");Assert.assertEquals(userDto.getAge(),12);}}

以上示例参考MapStruct官网的例子,例子中使用了lombok插件,请自行添加相关依赖和插件后使用。

MapStruct原理说明

target/generated-sources/annotations 里可以看到,代码中可以看到其生成了一个实现类, 而代码也类似于我们手写。这个在编译期生成的代码,性能比反射要快不少。

MapStruct是利用编译期动态生成set/get代码的class文件 ,在运行时直接调用该class文件。 该方式实际上仍会存在set/get代码,只是不需要自己手写。

MapStruct 转换方式

属性名称相同,直接转化,类似BeanUtils的转换防守

属性名不相同, 可通过 @Mapping 注解进行指定转化 例 @Mapping(source = "userName", target = "name")

MapStruct使用注意

当多个对象中,有其中一个为 null,则会直接返回 null

如一对一转换一样,属性通过名字来自动匹配。因此,名称和类型相同的不需要进行特殊处理

当多个原对象中,有相同名字的属性时,需要通过 @Mapping 注解来具体的指定,以免出现歧义

当有多个属性不一致时,有两种解决方式

添加多个@Mapping(推荐)

用@Mappings将多个@Mapping包起来(sonar检测会告警,不影响使用)

参考资料

官网:mapstruct.org/

Github地址:https://github.com/mapstruct/mapstruct/

实例分享:https://github.com/mapstruct/mapstruct-examples


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:/java/53.html