前言
在Java系统中经常要对不同数据类型对象如VO/DTO/BO等进行转换,传统写法用 Getter/Setter 方法复制属性非常繁琐且代码可读性差,有些人会使用 BeanUtil.copyproperties 方法转换属性,但该方法用反射方式实现,在数据量大的时候存在性能问题,且只支持名称和类型完全相同的属性之间转换,不够灵活;基于上面的问题,我推荐使用 MapstructPlus 框架,MapstructPlus 是 Mapstruct 的增强工具,在 Mapstruct 的基础上,实现了自动生成 Mapper 接口的功能,生成的代码是基于 Getter/Setter 方法,不会有较大的性能消耗,使 Java 类型转换更加便捷、优雅。
1.引入依赖
这里我推荐一个IDEA插件maven-search,方便快速搜索和复制maven依赖
1).若项目中引入了lombok,官方文档提供了整合Lombok的Maven配置
2).若项目中有jar包引入了MapStruct,为避免冲突最好排除掉,官方文档有提到Mapstruct依赖冲突问题
maven引入依赖配置,项目中swagger2模块存在Mapstruct,故在配置中排除了
1 | <!-- 依赖版本号 --> |
maven编译插件配置,整合Lombok在编译时自动生成代码
1 | <build> |
2.示例代码
配置多个类转换、配置指定类转换的规则等更多使用方法参考MapstructPlus 官方文档 和 MapStruct官方文档 ,这里就不展开了。
- 方式1:实体类添加
@AutoMapper注解
如果能直接修改其中一个实体类,那么只需要其中一个实体类添加@AutoMapper注解,就可以实现两者之间的转换。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35import io.github.linpeilie.annotations.AutoMapMapper;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
/**
* @author yinshuang
* @date 2023/7/19 20:43
* @description UserAttrVO
*/
public class UserAttrVO {
/**
* 物理主键
*/
private Long userId;
/**
* 角色
*/
private String role;
/**
* 所属部门
*/
private String department;
/**
* 岗位
*/
private String position;
}用 @AutoWare 或 @Resource 注解注入Convertor后,使用1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
import io.github.linpeilie.annotations.AutoMapMapper;
import lombok.Data;
/**
* @author yinshuang
* @date 2023/7/19 20:42
* @description UserBasicVO
*/
public class UserBasicVO {
/**
* 物理主键
*/
private Long userId;
/**
* 用户账号
*/
private String username;
/**
* 用户昵称
*/
private String nickName;
/**
* 手机号码
*/
private String mobile;
/**
* 电子邮箱
*/
private String email;
/**
* 角色
*/
private String role;
/**
* 所属部门
*/
private String department;
/**
* 岗位
*/
private String position;
}convert方法即可。 - 方式2:Mapstruct用法,定义Mapper接口添加
@Mapper注解
适用于无法修改实体类源码的场景
componentModel: 指定Mapper模式(实现类添加指定的注解类型),可选值有:default、cdi、spring、jsr330和jakarta。default: 默认情况,可以通过Mappers.getMapper(Class)方式获取实例对象;cdi: 生成的实现类上面会添加 @ApplicationScoped 注解,可以通过 @Inject 注解获取实例对象;spring: 生成的实现类上面会添加 @Component 注解,可以通过 @Autowired 或 @Resource 注解获取实例对象jsr330: 生成的实现类上面会添加 @javax.inject.Named 和 @Singleton 注解,可以通过 @Inject 注解获取实例对象;jakarta: 生成的实现类上面会添加 @RequestScoped 注解,可以通过 @Inject 注解获取实例对象。
1 | import com.xxx.vo.UserAttrVO; |
用 @AutoWare 或 @Resource 注解注入UserAttrMapper后,使用UserAttrMapper接口中定义方法即可。
- 方式3:MapstructPlus用法,定义Mapper接口添加
@Mapper注解,并且extends BaseMapper<S,T>
适用于无法修改实体类源码的场景用 @AutoWare 或 @Resource 注解注入UserAttrMapper或Convertor,使用1
2
3
4
5
6
7
8
9
10
11
12import com.xxx.vo.UserAttrVO;
import com.xxx.vo.UserBasicVO;
import io.github.linpeilie.BaseMapper;
import org.mapstruct.Mapper;
import org.mapstruct.MappingConstants;
import java.util.List;
public interface UserAttrMapper extends BaseMapper<UserAttrVO, UserBasicVO> {
}convert方法即可。
2.测试类代码
1 | import com.xxx.vo.UserAttrVO; |
3.生成代码
下面是加上 @AutoMapper 和 @AutoMapMapper 注解后,MapStruct Plus 框架自动生成的代码;
自动生生成的代码在对应模块根目录的 /target/generated-sources/annotations/ 中,
第一类是MapStruct Puls 相关的配置类,第二类是extends BaseMapMapper 的接口和对应的实现
1).MapStruct Puls 相关的配置类
1 | package io.github.linpeilie; |
1 | package io.github.linpeilie; |
1 | package io.github.linpeilie; |
1 | package io.github.linpeilie; |
2).Mapper 接口和对应的实现
以UserAttrVO为例,UserBasicVO类似就不列举了
1 | package com.xxx.vo; |
1 | package com.xxx.vo; |
1 | package com.xxx.vo; |
1 | package com.xxx.vo; |
- 本文作者: yinshuang
- 本文链接: https://yinshuang007.github.io/2023/07/19/Java类型转换框架Mapstruct-Plus使用分享/
- 版权声明: 本博客所有文章除特别声明外,均采用 MIT 许可协议。转载请注明出处!