几种实体拷贝方式实战(拷贝如何使用)

createh54个月前 (02-01)技术教程29

背景

我们有这样一个场景,有一个StudentDto类,还有一个StudentVo类

@Data

public class StudentDto {

private String id;

private String code;

private String sex;

private String userName;

}

@Data

public class StudentVo {

private String id;

private String name;

private String code;

private String age;

private String score;

private String sex;

}

问题

如果我们知道StudentVo的值,需要将StudentVo的属性拷贝到StudentDto中,你会怎么做。

StudentVo的值如下

public StudentVo initVo() {

StudentVo studentVo = new StudentVo();

studentVo.setId("1");

studentVo.setAge("27");

studentVo.setName("Lvshen");

studentVo.setCode("001");

studentVo.setScore("100");

studentVo.setSex("male");

return studentVo;

}

解决一

传统的解决方法,通过getter/setter方法将对应的属性值进行拷贝。

@org.junit.Test

public void test3() {

StudentVo studentVo = initVo();

StudentDto studentDto = new StudentDto();

studentDto.setCode(studentVo.getCode());

studentDto.setId(studentVo.getId());

studentDto.setSex(studentVo.getSex());

studentDto.setUserName(studentVo.getName());

System.out.println(studentDto);

}

测试结果

看了上面的方法,你可能觉得不是很简单么。但如果属性非常多,比如有20多个。用上面的方法就会不美观,满屏的getter/setter方法,看着都眼花。

解决二

这时我们就可以使用BeanUtils.copyProperties方法啦,这里的BeanUtils是Spring的,而不是apache的。

@org.junit.Test

public void test2() {

StudentVo studentVo = initVo();

StudentDto studentDto = new StudentDto();

BeanUtils.copyProperties(studentVo,studentDto);

System.out.println(studentDto);

}

测试结果

解决三(推荐)

我们还可以使用性能更优越的MapStruct,你可能没有听过这个东西。没关系,我们直接上代码。

MapStruct是一个可以生成类型安全的,高性能的且无依赖的 JavaBean 映射代码的注解处理器,可以在编译期生成对应的mapping,既没有BeanUtils等工具使用反射的性能问题,又免去了自己写映射代码的繁琐。

引入Maven依赖

org.mapstruct

mapstruct

1.3.1.Final

org.mapstruct

mapstruct-processor

1.3.1.Final

实体拷贝

我们先编写一个StudentConverter类

@Mapper

public interface StudentConverter {

StudentConverter INSTANCE = Mappers.getMapper(StudentConverter.class);

@Mappings(@Mapping(source = "name",target = "userName"))

StudentDto vo2dto(StudentVo vo);

}

这里的@Mapper来源于org.mapstruct.Mapper,用来说明这是一个实体转换类接口。

@Mappings用来声明成员属性的映射,source = "name",target = "userName"即将StudentVo中name的值拷贝给StudentDto中的userName,如果属性名称相同,就不需要做这个映射。

测试结果

@org.junit.Test

public void test1() {

StudentVo studentVo = initVo();

StudentDto studentDto = StudentConverter.INSTANCE.vo2dto(studentVo);

System.out.println(studentDto);

}

List集合拷贝

你以为MapStruct只能进行实体之间的拷贝?NO,MapStruct还可以进行List之间的拷贝,这个就太牛了。

@Mapper

public interface StudentConverter {

StudentConverter INSTANCE = Mappers.getMapper(StudentConverter.class);

@Mappings(@Mapping(source = "name",target = "userName"))

StudentDto vo2dto(StudentVo vo);

List listVo2dto(List vos);

}

测试

public void test() {

List voList = initVoList();

List studentDtos = StudentConverter.INSTANCE.listVo2dto(voList);

System.out.println(studentDtos);

}

测试结果

当然MapStruct等功能远比你想象的要多,有兴趣的可以看看这篇文章

https://www.cnblogs.com/homejim/p/11313128.html

我为什么推荐使用MapStruct

市面上 BeanUtils底层是使用反射的,我们知道使用反射会影响性能。而且BeanUtils需要类型和名称都一样才会进行映射, 但在很多时候, 由于不同的团队之间使用的名词不一样, 还是需要很多的手动使用getter/setter。

于是MapStruct诞生了。

MapSturct 是一个生成类型安全, 高性能且无依赖的 JavaBean 映射代码的注解处理器(annotation processor)。

它有下面几个特点:

“基于注解的处理器可以自定义 JavaBean 之间的属性映射类型安全, 高性能, 无依赖性”

编译之后会生成方法实现

实现的类、方法如下

该工具可以帮我们实现 JavaBean 之间的转换, 通过注解的方式。通过 MapStruct 来生成的代码, 其类似于人手写。速度上可以得到保证。

相关文章

你还在用BeanUtils进行对象属性拷贝?

在做业务的时候,为了隔离变化,我们会将DAO查询出来的DO和对前端提供的DTO隔离开来。大概90%的时候,它们的结构都是类似的;但是我们很不喜欢写很多冗长的b.setF1(a.getF1())这样的代...

Java的深拷贝与浅拷贝详解(java的深拷贝与浅拷贝详解图)

前言拷贝,顾名思义,就是复制一个一模一样的东西。那么放到对象上,也就是复制一个一模一样的对象了。Java中的数据类型分为基本数据类型和引用数据类型。对于这两种数据类型,在进行赋值操作、用作方法参数或返...

java对象深拷贝的三种实现方式,可避免循环引用导致的堆栈溢出

在java编程中,难免要对一个对象进行复制,复制分为深拷贝和浅拷贝。浅拷贝只复制对象本身,对于对象引用的其他对象不进行复制。 深拷贝则将对象与引用对象,全部进行拷贝。最简单的深拷贝就是自己new一个对...

Java中的深拷贝和浅拷贝的原理以及区别

深拷贝(Deep Copy)和浅拷贝(Shallow Copy)是在Java编程中与对象复制有关的两个概念,表面上看二者都可以实现对象的复制,但是在复制的方式以及实现效果上却有着很大的区别,下面我们就...

Java:深拷贝与浅拷贝(Cloneable接口)

文章目录1. Cloneable接口的介绍2. 浅拷贝的介绍和实例3. 深拷贝的介绍和实例1. Cloneable接口的介绍Cloneable是标记型的接口(空接口),它们内部都没有方法和属性, 实现...