MapStruct DTO对象数据复制

对象数据复制 MapStruct

MapStruct 的作用是什么?

项目开发的时候,页面发送的数据结构和数据库表的结构很多时候并不一致,我们通常会写 DTO 对象

  1. 页面数据和控制器交换用 DTO
  2. 数据库和数据模型交换数据用 DAO

那么 DTO 和 DAO 相互转换的时候,需要我们手动调用 set 方法,请注意下面用了 lombok 来生成代码

import lombok.Data;

@Data
public class StudentDto {
    private String userName;
    private String userId;
    private String address;
    private String school;
    private int age;
    private String email;

}

//==============================================================

import lombok.Builder;
import lombok.Data;

@Data
@Builder
public class Student {
    private String userName;
    private String userId;
    private String address;
    private String school;
    private int age;
    private String emailAddress;
    
    public Student(){}

    public Student(String userName, String userId, String address, String school, int age, String emailAddress) {
        this.userName = userName;
        this.userId = userId;
        this.address = address;
        this.school = school;
        this.age = age;
        this.emailAddress = emailAddress;
    }
}    

我们手动调用 set 方法来传递数据

Student vo = new Student();
vo.setUserId("A123");
vo.setUserName("Jack");


StudentDto dto = new StudentDto();

dto.setUserId(  vo.getUserId() );
dto.setUserName( vo.getUserName() );
.....

这种代码低效,我们就想者能不能写个工具,帮助我们复制数据,于是就有了 MapStruct

引入 POM

<dependency>
    <groupId>org.mapstructgroupId>
    <artifactId>mapstruct-processorartifactId>
    <version>1.4.2.Finalversion>
dependency>
<dependency>
    <groupId>org.mapstructgroupId>
    <artifactId>mapstructartifactId>
    <version>1.4.2.Finalversion>
dependency>

<dependency>
    <groupId>org.projectlombokgroupId>
    <artifactId>lombok-mapstruct-bindingartifactId>
    <version>0.2.0version>
dependency>

添加转换代码

import org.mapstruct.Mapper;
import org.merlin.project.cloudhospital.bean.Student;
import org.merlin.project.cloudhospital.dto.StudentDto;

@Mapper
public interface StudentConvert {
    
    StudentConvert INSTANCE = Mappers.getMapper(StudentConvert.class);

    Student convertStudent(StudentDto studentDto);


    StudentDto convertStudentDTO(Student student);
}

测试

下面这段代码测试时请注意,2个类都有使用 lombok 生成方法,默认和 MapStruct 是有冲突的,所以POM一定要引入 lombok-mapstruct-binding。这样测试就是正常的

@Test
void testSimpleMap() {
    StudentVo studentVo = StudentVo.builder()
        .school("郑州大学")
        .userId("A369")
        .userName("张三")
        .age(99)
        .address("郑州")
        .build();
    StudentDto studentDto = mainMapper.studentVo2Dto(studentVo);
    System.out.println(studentDto);
}

解决2个类中属性名不同,值无法复制的问题

studenVo和studenDto 有email 和emailAddress 字段不一致,可以通过 @Mapping 解决

import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.merlin.project.cloudhospital.bean.Student;
import org.merlin.project.cloudhospital.dto.StudentDto;

@Mapper
public interface StudentConvert {
    
   StudentConvert INSTANCE = Mappers.getMapper(StudentConvert.class);

    @Mapping(source = "email" , target = "emailAddress")
    Student convertStudent(StudentDto studentDto);

    @Mapping(source = "emailAddress" , target = "email")
    StudentDto convertStudentDTO(Student student);
}

List 复制

Student student = Student.builder().userId("123").userName("Jack").emailAddress("[email protected]").build();

Student student2 = Student.builder().userId("222").userName("张三").emailAddress("[email protected]").build();

List<Student> list = List.of(student, student2);

List<StudentDto> studentDtos = StudentConvert.INSTANCE.convertStudentDTOList(list);

studentDtos.forEach( studentDto -> System.out.println(studentDto));

复杂对象结构

新增类 Grade

@Data
public class Grade {

    private Integer gradeId;
    private String gradeName;
}

修改 Student

@Data
@Builder
public class Student {
    private String userName;
    private String userId;
    private String address;
    private String school;
    private int age;
    private String emailAddress;

    private Grade grade;

    private List<Grade> grades = new ArrayList<>();
    
    public Student(){}

    public Student(String userName, String userId, String address, String school, int age, String emailAddress, Grade grade, List<Grade> grades) {
        this.userName = userName;
        this.userId = userId;
        this.address = address;
        this.school = school;
        this.age = age;
        this.emailAddress = emailAddress;
        this.grade = grade;
        this.grades = grades;
    }
}

修改 StudentDTO

@Data
public class StudentDto {
    private String userName;
    private String userId;
    private String address;
    private String school;
    private int age;
    private String email;

    private Grade grade;

    private List<Grade> grades = new ArrayList<>();
}

修改 StudentConvert

import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Named;
import org.mapstruct.factory.Mappers;
import org.merlin.project.cloudhospital.bean.Grade;
import org.merlin.project.cloudhospital.bean.Student;
import org.merlin.project.cloudhospital.dto.StudentDto;

import java.util.List;

@Mapper
public interface StudentConvert {

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

    @Mapping(source = "email" , target = "emailAddress")
    Student convertStudent(StudentDto studentDto);


    /**
     * 当出现多个相同参数和返回值的方法,我们需要为方法提供标识,以供 MapStruct 能够明白调用那个方法
     * @param student
     * @return
     */
    @Named("one")
    @Mapping(source = "emailAddress" , target = "email")
    StudentDto convertStudentDTO(Student student);



    List<StudentDto> convertStudentListDTO(List<Student> students);

    @Named("two")
    @Mapping(source = "emailAddress" , target = "email")
    default StudentDto convertStudentExtDTO(Student student) {
        if( student == null) {
            return  null;
        }

        StudentDto studentDto = convertStudentDTO(student);

        studentDto.setGrade( student.getGrade() );

        List<Grade> grades = student.getGrades();
        studentDto.setGrades( grades );
        return  studentDto;
    }

}

测试

@Test
void contextLoads() {

    Student student = Student.builder().userId("123").userName("Jack").emailAddress("[email protected]").build();

    Grade g1 = new Grade();
    g1.setGradeId(1);
    g1.setGradeName("一年级");

    Grade g2 = new Grade();
    g2.setGradeId(2);
    g2.setGradeName("2年级");

    List<Grade> gradeList = List.of(g1, g2);
    student.setGrades( gradeList );

    student.setGrade(g1);

    StudentDto studentDto = 
        StudentConvert.INSTANCE.convertStudentExtDTO(student);
    
    System.out.println(studentDto);
}

你可能感兴趣的:(java,数据库,mybatis)