为什么要使用MapStruct而不是BeanUtils.copyProperties?
为什么要使用MapStruct而不是BeanUtils.copyProperties?
本人在一家小公司刚实习的时候,还是保留了之前在网上学习项目时候的习惯,例如数据库实体类和VO类的属性赋值,还是使用了BeanUtils.copyProperties,每次我写完一个接口,公司那位带我的大佬就会帮我纠正一些不好的习惯或者是提醒我怎么优化,让我改用MapStruct替代BeanUtils.copyProperties,既然要替换,那肯定就要思考替换的理由了。
BeanUtils.copyProperties的使用方法很简单,下面便不会做示例了。
BeanUtils 和 MapStruct对比
性能上:MapStruct 比 BeanUtils更快,BeanUtils 他是采用反射的机制动态去进行拷贝映射,而MapStruct采用的是单纯的 get 和 set 方法。
便利性上:BeanUtils确实更快,因为用法很简单,而MapStruct的用法相对麻烦一点,需要编写新的接口和对应映射方法(不用实现),但是,MapStruct还支持多数据源,也就是使用多个Vo的属性拿来映射。
下面主要介绍MapStruct用法,BeanUtils那个很简单下面便不会做示例了。
MapStruct 用法
依赖准备
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>1.4.2.Final</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>1.4.2.Final</version>
<scope>compile</scope>
</dependency>
接口准备
准备一个convertor包,然后新建一个Convertor类
/**
* @author liangry
* @create 2022/9/23 9:13
* spring注入方式
*/
@Mapper(componentModel = "spring")
public interface StudentConvertor {
/**
* 普通转换,字段名对应就会相应的赋值,如果Student没有ClassName字段,则即使Vo有,也不会有什么问题
* @param studentVo
* @return
*/
Student fromStudentVo(StudentVo studentVo);
/**
* 自定义映射转换(多数据源),有时候可能原始类和目标类的某些字段名可能不相同,进行一个指定映射
* @param userVo 用户名字赋值给学生名字
* @param teacherVo 教师工号赋值给学生学号(只是为了方便假设)
* @return
*/
@Mappings({
@Mapping(source = "userVo.name",target = "name"),
@Mapping(source = "teacherVo.tno",target = "sno")
})
Student fromTeacherVoAndUserVo(UserVo userVo, TeacherVo teacherVo);
/**
* List 映射
* @param studentVoList
* @return
*/
List<Student> fromStudentVoList(List<StudentVo> studentVoList);
}
在Controller接口模拟
/**
* 模拟多数据源和List映射,至于单数据源,读者应该能够看得懂,根据接口直接调用方法传参
*/
@ApiOperation("testMapStruct")
@GetMapping("/testMapStruct")
public void testMapStruct() {
UserVo userVo = new UserVo();
userVo.setName("李白");
TeacherVo teacherVo = new TeacherVo();
teacherVo.setTno("1183010");
Student student = studentConvertor.fromTeacherVoAndUserVo(userVo, teacherVo);
System.out.println("查看情况多数据源映射情况" + student.toString());
//=======下面是list映射=======
List<StudentVo> studentVos = new ArrayList<>();
//链式编程,在StudentVo类上面加上 @Accessors(chain = true) 注解即可
studentVos.add(new StudentVo().setName("张三").setAge(18).setClassId(110L));
studentVos.add(new StudentVo().setName("李四").setAge(18).setClassId(110L));
studentVos.add(new StudentVo().setName("王五").setAge(18).setClassId(110L));
List<Student> students = studentConvertor.fromStudentVoList(studentVos);
//输出查看情况
students.forEach(System.out::println);
}
补充
还有一些别的功能,后面再找时间补充,比如说类型映射、逆映射、自定义映射方法使用其他值、使用表达式映射赋值。
参考文章:https://blog.youkuaiyun.com/qq_44732146/article/details/119968376