Mapstruct 基本用法

MapStruct 简介

在实际开发我们经常要在项目中进行 DTO、VO、DO、Entity 等实体之间的转换,这种类型的框架和工具类也有很多,比如 Spring 框架中的 BeanUtils 工具类 ,但这个工具类是通过反射来实现的,性能相对低下且存在类型转换异常的问题,所以这个工具在有些公司是禁止使用的。下面简单说一下MapStruct,MapStruct 是一个代码生成器,它基于约定优于配置的方法极大地简化了Java bean类型之间映射的实现。与其他映射框架相比,MapStruct在编译时生成Bean映射,以确保高性能,允许快速的开发人员反馈和彻底的错误检查。

MapStruct 官网 https://mapstruct.org/

技术比较

在这里插入图片描述

案例

一、新建 Maven 项目,并导入以下依赖

<!--mapStruct依赖-->
		<dependency>
			<groupId>org.mapstruct</groupId>
			<artifactId>mapstruct</artifactId>
			<version>1.4.1.Final</version>
		</dependency>
		<dependency>
			<groupId>org.mapstruct</groupId>
			<artifactId>mapstruct-jdk8</artifactId>
			<version>1.4.1.Final</version>
		</dependency>
		<dependency>
			<groupId>org.mapstruct</groupId>
			<artifactId>mapstruct-processor</artifactId>
			<version>1.4.1.Final</version>
		</dependency>

二、创建 entity、DTO、VO 类

1、创建 Member 实体类

public class Member {
	private String id;
	private String memberName;
	private String password;
	private String phone;
	private String address;

	// 省略getter setter
}

2、创建 MemberDTO

public class MemberDTO {
	private String memberName;
	private String phone;
	private String address;
	// 省略getter setter
}

3、创建 MemberVO

public class MemberVo {
	private String id;
	private String memberName;
	// private String password;
	private String phone;
	private String address;
	// 省略getter setter
}

三、定义 MapStruct 映射接口

/**
 * @author wfd
 * @description
 * @create 2021/3/29 23:22
 */

@Mapper
public interface MemberMapstruct {

	MemberMapstruct MEMBER_MAPSTRUCT = Mappers.getMapper(MemberMapstruct.class);

	/**
	 * member 转为 memberVO
	 * @param member
	 * @return
	 */
	MemberVo memberToMemberVO(Member member);

	/**
	 * memberVo 转为 member
	 * @param memberVo
	 * @return
	 */
	Member MemberVOToMember(MemberVo memberVo);

	/**
	 * memberVo 转为 MemberDto
	 * @param memberVo
	 * @return
	 */
	MemberDTO memberVoToMemberDto(MemberVo memberVo);

}

四、测试

public class MapStructTest {
	public static void main(String[] args) {
		Member member = new Member();
		member.setMemberName("wfd");
		member.setPassword("ojd");
		member.setId("123456");
		member.setPhone("13400000000");
		member.setAddress("gz");

		/**
		 * member 转为 memberVO
		 */
		MemberVo memberVo = MemberMapstruct.MEMBER_MAPSTRUCT.memberToMemberVO(member);
		System.out.println("memberVo = " + memberVo);

		/**
		 * memberVo 转为 MemberDto
		 */
		MemberDTO memberDTO = MemberMapstruct.MEMBER_MAPSTRUCT.memberVoToMemberDto(memberVo);
		System.out.println("memberDTO = " + memberDTO);

	}
}

测试结果

memberVo = MemberVo{id='123456', memberName='wfd', phone='13400000000', address='gz'}
memberDTO = MemberDto{memberName='wfd', phone='13400000000', address='gz'}

可以看到项目编译的时候,自动生成了 MemberMapStructImpl这个实现类,打开这个实现类可以看到,实体之间在转换时会先新建一个实例对象,然后再通过setter方法进行赋值,并不是通过反射进行赋值,这也是为什么MapStruct的性能相对较好的原因。
在这里插入图片描述

总结

看完这篇文章可能有些小伙伴会感到困惑,MapStruct 进行实体转换的时候,如果有多个DTO、VO、Entity 进行转换的话,那么就要定义对应数量的方法才行,这样似乎看起来变得更麻烦了,直接使用 getter 和 setter 或者使用 BeanUtils 岂不是更为方便了 ?还不用引入 MapStruct 的 相关概念。其实在进行技术选型的时候,得配合应用场景来使用,如果实体的字段比较少,固然直接使用 getter setter 方法最为方便,但是当你的字段过多,一个实体七八十个字段的时候,那肯定是使用这些映射框架比较方便,且代码比较简洁。所以得具体问题,具体分析啦!!!

学习过程中遇到的问题

编译顺序问题

1、mapstruct 和 lombok 编译顺序问题,报以下错误

java: You aren't using a compiler supported by lombok, so lombok will not work and has been disabled.
  Your processor is: com.sun.proxy.$Proxy26
  Lombok supports: OpenJDK javac, ECJ

2、原因:使用lombok后,project在编译时,会生成包含了getter与setter的Source code.
使用mapstruct后,project在编译时,会生成mapper的具体实现类
mapstruct与lombok一起使用使时有时候会有到编译顺序的问题
当lombok的Source Code 未生成时,生成的mapper实现,将会缺少很多属性字段

3、解决方案:修改 maven 编译时的执行顺序

<build>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.8.1</version>
				<configuration>
					<source>8</source>
					<target>8</target>
					<compilerArgs>--enable-preview</compilerArgs>
					<annotationProcessorPaths>
						<path>
							<groupId>org.projectlombok</groupId>
							<artifactId>lombok</artifactId>
							<version>${lombok.version}</version>
						</path>
						<path>
							<groupId>org.mapstruct</groupId>
							<artifactId>mapstruct-processor</artifactId>
							<version>1.4.1.Final</version>
						</path>
					</annotationProcessorPaths>
				</configuration>
			</plugin>
		</plugins>
	</build>

缓存问题

因为MapStruct在编译时期就将代码生成,如果我们一开始的文件名是 AA ,后来因为其他的原因改为了 BB,那么之前生成 AA 文件还是会保存在 target目录下的,这样会出现一种情况,就是你在自己本地可以跑项目,但是上了服务可能就会产生 文件找不到的异常,所以建议只要是修改了Mapstruct 相关的,就先 clean 一下,再重新编译
在这里插入图片描述

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值