当前位置: 首页 > news >正文

属性映射框架-MapStruct

在这里插入图片描述

属性映射框架-MapStruct

文章目录

  • 属性映射框架-MapStruct
  • 一、作用
  • 二、MapStruct 简介
    • 2.1 是什么
    • 2.2 竞品框架
    • 2.3 适合场景
  • 三、入门案例
    • 3.1 项目需求
    • 3.2 代码实现
  • 四、入门案例解析
  • 五、MapStruct 实战
    • 5.1 当属性正常映射时
    • 5.2 当某个属性要忽略映射
    • 5.3 当某个属性要求设置默认值时
    • 5.4 当属性名不一致时
    • 5.5 当源对象是多个时
    • 5.6 当属性为对象时
    • 5.7 当目标对象已经存在时
    • 5.8 当属性类型对不上时
      • 5.8.1 源是时间,目标是字符串
      • 5.8.2 源是字符串,目标是枚举
    • 5.9 当源是集合时
  • 六、SpringBoot集成
  • 七、项目实战

一、作用

MapStruct 是一个基于 Java 注解处理器的代码生成工具,主要用于简化 Java Bean 之间的映射转换。它通过编译时生成类型安全的映射代码,替代了传统手动编写转换逻辑的繁琐过程,显著提升开发效率和代码质量。

二、MapStruct 简介

2.1 是什么

官网:https://mapstruct.org/

在这里插入图片描述

What

MapStruct是一个代码生成器,它极大地简化了基于约定优于配置方法的Java Bean类型之间映射的实现。

生成的映射代码使用普通的方法调用,因此速度快、类型安全且易于理解。

大白话:一种代码生成器,解决Java Bean间属性映射

Why

MapStruct是一个Java注解处理器,用于自动生成对象之间的映射代码。在多层应用程序中,通常需要在不同的对象模型(如实体和数据传输对象DTOs)之间进行映射。手动编写这些映射代码既繁琐又容易出错。MapStruct通过自动化这个过程来简化这项工作。

大白话:Java各种O中来回转换既繁琐又容易出错,MapStruct可以轻松解决

注意点:Java各种O后面会解释,这里理解为Java Bean即可

How

MapStruct是一个注解处理器,它被插入到Java编译器中,可以在命令行构建(Maven,Gradle等)中使用,也可以从您喜欢的IDE中使用。

MapStruct使用合理的默认值,但在配置或实现特殊行为时,它会避开您的方式。

大白话:可手动可自动

案例感受一下:

需求:属性复制

public class User{private String uname;private String pwd;
}public class Person{private String name;private String password;
}

没用MapStruct之前

User u = new User("dafei", "666");
Person p = new Person();
p.setName(u.getUname());
p.setPassword(u.getPwd());    

用了MapStruct之后

User u = new User("dafei", "666");
Person p = UserMapper.INSTANCE.toPerson(u);

当前字段少,感受不出MapStruct魅力,如果复制的字段是100,200个时,就有你哭的啦。

2.2 竞品框架

看到这,肯定有小可爱说,直接用BeanUtil.copyProperties 不就得了么?那来比较一下。

市面上实现上面属性复制/映射的框架/方法有很多

  • Spring BeanUtils
  • Cglib BeanCopier
  • Apache BeanUtils
  • Dozer
  • orika
  • MapStruct
  • JSON 序列化 再反序列化
工具实现方式缺点说明
MapStructgetter/setter方法需要了解注解和配置项语法JSR269注解处理器在编译期自动生成Java Bean转换代码,支持可配置化,扩展性强
orika动态生成字节码首次调用耗时较久,性能适中采用javassist类库生成Bean映射的字节码,之后直接加载执行生成的字节码文件
Spring BeanUtils反射机制不支持名称相同但类型不同的属性转换
Apache BeanUtils反射机制需要处理编译期异常,性能最差
dozer反射机制性能差使用reflect包下Field类的set(Object obj, Object value)方法进行属性赋值
BeanCopier反射机制BeanCopier只拷贝名称和类型都相同的属性。即便基本类型与其对应的包装类型也不能相互转换;使用ASM的MethodVisitor直接编写各属性的get/set方法
JSON 序列化 再反序列化借助其他Json工具转换源对象先转json字符串,再转目标对象,慢

实现1000000次属性拷贝:

@Data
public class Source {private Long id;private String name;private Date birth;private Double money;private List<String> sms;private BigDecimal price;
}
@Data
public class Target {private Long id;private String name;private Date birth;private Double money;private List<String> sms;private BigDecimal price;
}

第一次:

Apache BeanUtilsSpring BeanUtilsMapStructOrikaDozerBeanCopier
5.06478990.26214970.02319920.494166215.28181630.0086604

第二次:

Apache BeanUtilsSpring BeanUtilsMapStructOrikaDozerBeanCopier
5.13250040.26599470.02365350.482508715.77854510.0097842

第三次:

Apache BeanUtilsSpring BeanUtilsMapStructOrikaDozerBeanCopier
4.91202560.27924790.02352940.509464815.70236850.0094256

从上面的测试

性能由高到低

BeanCopier > MapStruct > Spring BeanUtils > Orika > Apache BeanUtils > Dozer

​ 1 2.5 30 54 520 1665

结论:

按理 BeanCopier 性能最佳,但是它有个明显的缺陷:属性名与类型必须完全匹配才能转换

MapStruct 最好

2.3 适合场景

MapStruct适用于各种Java Bean之间的转换场景,包括但不限于以下情况:

  1. DTO(Data Transfer Object)数据接收对象 和 Entity(PO)即实体类它与数据库表中的字段是一一对应的之间的转换。
  2. 不同版本API之间的数据映射。
  3. 前端页面展示数据和后端数据模型之间的转换。

大白话:各种O之间转换

问题:Java中有哪些O,为什么存在各种O

  • POJO(plian ordinary java object)

    简单普通的Java对象,就是最简单的Java对象,最基本的Java Bean只是在属性上加上get和set方法

  • PO(Persistent Object)
    持久对象,与数据库表中字段一一对应,一般一个表对应一个PO,直接与数据库的crud操作相关。

  • VO(Value Object)
    VO有人理解为Value Object,也有人理解为View Object,无论是那种定义,其表达的意思是:表现层对象,用于业务层之间的数据传递,其作用与PO类似,但是其是与页面层相关,一般将页面层的数据封装成一个VO传递给页面,此处的VO可以继承与PO以减少冗余代码。

  • DTO(Data Trasfer Object)
    数据传输对象,一般用于向外提供仅需的数据,此处类似于VO的作用,如从数据库中查询出有30个字段,但是接口所需其中的10个字段,那么可在此处将10个字段封装成一个DTO提供给外部接口,以隐藏数据层的字段,也可减少数据的传输,提高系统性能。

  • BO(Business Object)/DO(Domain Object)
    业务对象/域对象,一般写在业务层,当业务逻辑比较复杂时,可能会用到比较多的业务对象,这样就可以将多个PO、VO封装成一个BO对象用于数据传递。

  • DAO(Data AccessObject)
    数据访问对象,就是一般我们所说的DAO层,用于连接数据库与service层的桥梁,用于对数据的访问(不是对数据库的访问),并且持久化数据层对象

在这里插入图片描述

大白话:各种O简单理解就是各个层级间数据流转对象

三、入门案例

3.1 项目需求

需求:实现将User对象属性拷贝到UserDTO中

3.2 代码实现

步骤1:创建项目

新建Maven项目:MapStrust-demo

步骤2:导入依赖

说明:这里使用的是-JDK-17

<dependencies><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.34</version></dependency><dependency><groupId>org.mapstruct</groupId><artifactId>mapstruct</artifactId><version>1.6.3</version></dependency><dependency><groupId>org.mapstruct</groupId><artifactId>mapstruct-processor</artifactId><version>1.6.3</version></dependency></dependencies>

步骤3:创建实体对象

@Data
@Accessors(chain = true)
public class User {private Long id;private String name;private String password;
}@Data
@Accessors(chain = true)
public class UserDTO {private Long id;private String name;private String password;
}

步骤4:编写映射接口

import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;@Mapper
public interface UserMapper {UserMapper INSTANCE = Mappers.getMapper( UserMapper.class );UserDTO userToUserDTO(User user);
}

这里有个注意点:@Mapper 是MapStruct 的, 注意跟MyBatis的 @Mapper区别

步骤5:拷贝实现

public class App {@Testpublic void testHello(){User user = new User().setId(1L).setName("dafei").setPassword("666");UserDTO userDTO = UserMapper.INSTANCE.userToUserDTO(user);System.out.println(user);System.out.println(userDTO);}
}
User(id=1, name=dafei, password=666)
UserDTO(id=1, name=dafei, password=666)

四、入门案例解析

  • lombok
@Data
@Accessors(chain = true)
public class User {private Long id;private String name;private String password;
}

@Data : 这个是lombok 插件,在编译期给User对象添加或重写get/set/toString/hashCode/equals等方法

@Accessors(chain = true)让User对象set方法改成链式方法

public User setId(Long id){this.id = id;return this
}
....

呈现出来的效果

User user = new User().setId(1L).setName("dafei").setPassword("666");
  • @Mapper
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;@Mapper
public interface UserMapper {UserMapper INSTANCE = Mappers.getMapper( UserMapper.class );UserDTO userToUserDTO(User user);
}

@Mapper 这个Mapper注解跟MyBatis的@Mapper注解功能类似,就是将贴到的接口通过动态代理方式直接创建出接口实现类:UserMapperImpl

在这里插入图片描述

public class UserMapperImpl implements UserMapper {public UserMapperImpl() {}public UserDTO userToUserDTO(User user) {if (user == null) {return null;} else {UserDTO userDTO = new UserDTO();userDTO.setId(user.getId());userDTO.setName(user.getName());userDTO.setPassword(user.getPassword());return userDTO;}}
}

观察就会发现底层实现原理就是普通的GET/SET操作

  • Mappers

一个工具类,如果说@Mapper注解是MapStruct框架推门者,Mappers就是MapStruct框架引路者

贴了@Mapper注解的接口会在项目运行时会在内存中动态创建一个实现类对象,那Mappers工具类就是将对象摆放到前台啦。

//获取Mapper接口实现类对象
UserMapper INSTANCE = Mappers.getMapper( UserMapper.class );

Mappers 是一个工厂类,通过传入的字节码对象,获取Mapper接口实现类,然后进行方法调用。

UserDTO userToUserDTO(User user);

五、MapStruct 实战

5.1 当属性正常映射时

需求:将Person 转换成PersonDTO

import lombok.Data;
import lombok.AllArgsConstructor;
@Data
@AllArgsConstructor
public class Person {private String name;private int age;
}
import lombok.Data;
@Data
public class PersonDTO {private String name;private int age;
}
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;@Mapper
public interface PersonMapper {PersonMapper INSTANCE = Mappers.getMapper(PersonMapper.class);PersonDTO toDTO(Person person);
}
public class App {public static void main(String[] args) {Person person = new Person("dafei", 18);System.out.println(person);PersonDTO dto = PersonMapper.INSTANCE.toDTO(person);System.err.println(dto);}
}
Person(name=dafei, age=18)
PersonDTO(name=dafei, age=18)

5.2 当某个属性要忽略映射

需求:将Person转换成PersonDTO,忽略age属性

import lombok.AllArgsConstructor;
import lombok.Data;@Data
@AllArgsConstructor
public class Person {private String name;private int age;
}
import lombok.AllArgsConstructor;
import lombok.Data;@Data
@AllArgsConstructor
public class PersonDTO {private String name;private int age;
}
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.factory.Mappers;@Mapper
public interface PersonMapper {PersonMapper INSTANCE = Mappers.getMapper(PersonMapper.class);@Mapping(target = "age", ignore = true)PersonDTO toDTO(Person person);
}
public class App {public static void main(String[] args) {Person person = new Person("dafei", 18);System.out.println(person);PersonDTO dto = PersonMapper.INSTANCE.toDTO(person);System.err.println(dto);}
}
Person(name=dafei, age=18)
PersonDTO(name=dafei, age=0)

5.3 当某个属性要求设置默认值时

需求:将Person转成PersonDTO,当name属性为null时,设置默认值:xiaofei

import lombok.AllArgsConstructor;
import lombok.Data;@Data
@AllArgsConstructor
public class Person {private String name;private int age;
}
import lombok.AllArgsConstructor;
import lombok.Data;@Data
@AllArgsConstructor
public class PersonDTO {private String name;private int age;
}
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.factory.Mappers;@Mapper
public interface PersonMapper {PersonMapper INSTANCE = Mappers.getMapper(PersonMapper.class);//当源对象name属性值为null时,使用默认值@Mapping(target = "name", defaultValue = "xiaofei")PersonDTO toDTO(Person person);
}
public class App {public static void main(String[] args) {Person person = new Person(null, 18);System.out.println(person);PersonDTO dto = PersonMapper.INSTANCE.toDTO(person);System.err.println(dto);}
}
Person(name=null, age=18)
PersonDTO(name=xiaofei, age=18)

5.4 当属性名不一致时

需求:将Person转成PersonDTO,属性名不一致要做映射

import lombok.Data;
import lombok.AllArgsConstructor;
@Data
@AllArgsConstructor
public class Person {private String name;private int age;
}
import lombok.Data;
@Data
public class PersonDTO {private String nameDTO;private int ageDTO;
}
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Mappings;
import org.mapstruct.factory.Mappers;@Mapper
public interface PersonMapper {PersonMapper INSTANCE = Mappers.getMapper(PersonMapper.class);@Mappings({@Mapping(source = "name", target = "nameDTO"),@Mapping(source = "age", target = "ageDTO")})PersonDTO toDTO(Person person);
}
public class App {public static void main(String[] args) {Person person = new Person("dafei", 18);System.out.println(person);PersonDTO dto = PersonMapper.INSTANCE.toDTO(person);System.err.println(dto);}
}
Person(name=dafei, age=18)
PersonDTO(nameDTO=dafei, ageDTO=18)

5.5 当源对象是多个时

需求:将Person, Phone转成PersonDTO

即:PersonDTO(name, age, phone) = Person(name, age) + Phone(id, phone)

import lombok.Data;
import lombok.AllArgsConstructor;
@Data
@AllArgsConstructor
public class Person {private String name;private int age;
}
import lombok.AllArgsConstructor;
import lombok.Data;@Data
@AllArgsConstructor
public class Phone {private Long id;private String phone;
}
import lombok.Data;@Data
public class PersonDTO {private String name;private int age;private String phone;
}

在这里插入图片描述

import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Mappings;
import org.mapstruct.factory.Mappers;@Mapper
public interface PersonMapper {PersonMapper INSTANCE = Mappers.getMapper(PersonMapper.class);@Mappings({@Mapping(source = "person.name", target = "name"),@Mapping(source = "person.age", target = "age"),@Mapping(source = "phone.phone", target = "phone")})PersonDTO toDTO(Person person, Phone phone);
}
public class App {public static void main(String[] args) {Person person = new Person("dafei", 18);System.out.println(person);Phone phone = new Phone(1L, "13700000000");System.out.println(phone);PersonDTO dto = PersonMapper.INSTANCE.toDTO(person, phone);System.err.println(dto);}
}
Person(name=dafei, age=18)
Phone(id=1, phone=13700000000)
PersonDTO(name=dafei, age=18, phone=13700000000)

5.6 当属性为对象时

需求:将Person, Phone转成PersonDTO, 其中Phone是PersonDTO的属性

import lombok.AllArgsConstructor;
import lombok.Data;@Data
@AllArgsConstructor
public class Person {private String name;private int age;
}
import lombok.AllArgsConstructor;
import lombok.Data;@Data
@AllArgsConstructor
public class Phone {private Long id;private String phone;
}
import lombok.Data;@Data
public class PersonDTO {private String name;private int age;private Phone phone;
}
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Mappings;
import org.mapstruct.factory.Mappers;@Mapper
public interface PersonMapper {PersonMapper INSTANCE = Mappers.getMapper(PersonMapper.class);@Mappings({@Mapping(source = "person.name", target = "name"),@Mapping(source = "person.age", target = "age"),@Mapping(source = "phone.id", target = "phone.id"),@Mapping(source = "phone.phone", target = "phone.phone"),})PersonDTO toDTO(Person person, Phone phone);
}
public class App {public static void main(String[] args) {Person person = new Person("dafei", 18);System.out.println(person);Phone phone = new Phone(1L, "13700000000");System.out.println(phone);PersonDTO dto = PersonMapper.INSTANCE.toDTO(person, phone);System.err.println(dto);}
}
Person(name=dafei, age=18)
Phone(id=1, phone=13700000000)
PersonDTO(name=dafei, age=18, phone=Phone(id=1, phone=13700000000))

5.7 当目标对象已经存在时

需求:将Person转成PersonDTO, 其中PersonDTO对象已经提前被创建好了

import lombok.AllArgsConstructor;
import lombok.Data;@Data
@AllArgsConstructor
public class Person {private String name;private int age;
}
import lombok.AllArgsConstructor;
import lombok.Data;@Data
@AllArgsConstructor
public class PersonDTO {private String name;private int age;
}
import org.mapstruct.Mapper;
import org.mapstruct.MappingTarget;
import org.mapstruct.factory.Mappers;@Mapper
public interface PersonMapper {PersonMapper INSTANCE = Mappers.getMapper(PersonMapper.class);void copy(Person source, @MappingTarget PersonDTO target);
}
public class App {public static void main(String[] args) {Person person = new Person("dafei", 18);System.out.println(person);PersonDTO dto = new PersonDTO("xiaofei", 17);PersonMapper.INSTANCE.copy(person, dto);System.err.println(dto);}
}
Person(name=dafei, age=18)
PersonDTO(name=dafei, age=18)

5.8 当属性类型对不上时

5.8.1 源是时间,目标是字符串

需求:将Person转成PersonDTO,Person有个属性是Date类型

import lombok.AllArgsConstructor;
import lombok.Data;import java.util.Date;@Data
@AllArgsConstructor
public class Person {private String name;private int age;private Date birth;
}
import lombok.AllArgsConstructor;
import lombok.Data;@Data
@AllArgsConstructor
public class PersonDTO {private String name;private int age;private String birth;
}
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.factory.Mappers;@Mapper
public interface PersonMapper {PersonMapper INSTANCE = Mappers.getMapper(PersonMapper.class);@Mapping(target = "birth", dateFormat = "yyyy-MM-dd")PersonDTO toDTO(Person person);
}
import java.util.Date;public class App {public static void main(String[] args) {Person person = new Person("dafei", 18, new Date());System.out.println(person);PersonDTO dto = PersonMapper.INSTANCE.toDTO(person);System.err.println(dto);}
}
Person(name=dafei, age=18, birth=Thu Dec 05 18:01:28 CST 2024)
PersonDTO(name=dafei, age=18, birth=2024-12-05)

5.8.2 源是字符串,目标是枚举

需求:将Person转成PersonDTO,PersonDTO有个属性是枚举类型

import lombok.AllArgsConstructor;
import lombok.Data;@Data
@AllArgsConstructor
public class Person {private String name;private int age;private String sex;
}
import lombok.Getter;public enum Sex {MAN("男"), WOMAN("女"),YAO("妖");@Getterprivate String name;private Sex(String name){this.name = name;}
}
import lombok.AllArgsConstructor;
import lombok.Data;@Data
@AllArgsConstructor
public class PersonDTO {private String name;private int age;private Sex sex;
}
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Named;
import org.mapstruct.factory.Mappers;@Mapper
public interface PersonMapper {PersonMapper INSTANCE = Mappers.getMapper(PersonMapper.class);@Mapping(target = "sex", source = "sex",  qualifiedByName = "mapStringToSex")PersonDTO toDTO(Person person);@Named("mapStringToSex")default Sex mapStringToSex(String sex){if (sex == null) {return null;}switch (sex) {case "男":return Sex.MAN;case "女":return Sex.WOMAN;case "妖":return Sex.YAO;default:throw new IllegalArgumentException("Unknown sex: " + sex);}}
}
public class App {public static void main(String[] args) {Person person = new Person("dafei", 18, "男");System.out.println(person);PersonDTO dto = PersonMapper.INSTANCE.toDTO(person);System.err.println(dto);}
}

5.9 当源是集合时

需求:将 List<Person>转成 List<PersonDTO>

import lombok.AllArgsConstructor;
import lombok.Data;@Data
@AllArgsConstructor
public class Person {private String name;private int age;
}
import lombok.AllArgsConstructor;
import lombok.Data;@Data
@AllArgsConstructor
public class PersonDTO {private String name;private int age;
}
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;import java.util.List;@Mapper
public interface PersonMapper {PersonMapper INSTANCE = Mappers.getMapper(PersonMapper.class);List<PersonDTO> toDTOList(List<Person> personList);
}
import java.util.ArrayList;
import java.util.List;public class App {public static void main(String[] args) {List<Person> personList = new ArrayList<>();for (int i = 0; i < 10; i++){personList.add(new Person("dafei_" + i, i));}List<PersonDTO> personDTOS = PersonMapper.INSTANCE.toDTOList(personList);personDTOS.forEach(System.out::println);}
}

六、SpringBoot集成

MapStruct基本操作算差不多了,来看下在SpringBoot环境下,该如何操作

步骤1:将项目改造成SpringBoot环境

<parent><artifactId>spring-boot-parent</artifactId><groupId>org.springframework.boot</groupId><version>2.7.11</version>
</parent><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId>
</dependency>

步骤2:具体代码

import lombok.AllArgsConstructor;
import lombok.Data;@Data
@AllArgsConstructor
public class Person {private String name;private int age;
}
import lombok.AllArgsConstructor;
import lombok.Data;@Data
@AllArgsConstructor
public class PersonDTO {private String name;private int age;
}
import org.mapstruct.Mapper;@Mapper(componentModel = "spring")
public interface PersonMapper {PersonDTO toDTO(Person person);
}

这里要注意@Mapper(componentModel = "spring") 表示将PersonMapper对象创建并交个Spring容器管理

步骤3:测试

启动类

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
public class App {public static void main(String[] args) {SpringApplication.run(App.class, args);}
}

测试类

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;@SpringBootTest
public class MapperTest {//直接引入即可@Autowiredprivate PersonMapper personMapper;@Testpublic void testDto(){Person person = new Person("dafei", 18);PersonDTO personDTO = personMapper.toDTO(person);System.out.println(personDTO);}
}

七、项目实战

需求:实现Bean对转换DTO, List<Bean> 转换List<DTO> Map<String, Bean>转换 Map<String, DTO>

步骤1:定义2个实体bean与DTO

import lombok.AllArgsConstructor;
import lombok.Data;@Data
@AllArgsConstructor
public class User {private Long id;private String username;private String password;
}import lombok.AllArgsConstructor;
import lombok.Data;@Data
@AllArgsConstructor
public class UserDTO {private Long id;private String username;private String password;
}
import lombok.AllArgsConstructor;
import lombok.Data;@Data
@AllArgsConstructor
public class Employee {private Long id;private String username;private String password;
}import lombok.AllArgsConstructor;
import lombok.Data;@Data
@AllArgsConstructor
public class EmployeeDTO {private Long id;private String username;private String password;
}

步骤2:转换规则与实现

import java.util.List;
import java.util.Map;/*** bean and dto transformation base mapper* @param <T>* @param <V>*/
public interface BaseConverter<T,V> {V bean2dto(T bean);T dto2bean(V dto);List<V> beans2dtoList(List<T> beans);List<T> dtoList2beans(List<V> dtoList);Map<String,V>beanMap2dtoMap(Map<String,T> beanMap);Map<String,T>dtoMap2beanMap(Map<String,V>dtoMap);Map<String,List<T>>dtoMapList2beanMapList(Map<String,List<V>>dtoMap);Map<String,List<V>>beanMapList2dtoMapList(Map<String,List<T>>beanMap);
}
import org.mapstruct.Mapper;@Mapper(componentModel = "spring")
public interface UserConverter extends BaseConverter<User, UserDTO>{
}
import org.mapstruct.Mapper;@Mapper(componentModel = "spring")
public interface EmployeeConverter extends BaseConverter<Employee, EmployeeDTO>{
}

步骤3:启动与测试

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
public class App {public static void main(String[] args) {SpringApplication.run(App.class, args);}
}
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;import java.util.Arrays;
import java.util.List;@SpringBootTest
public class MapperTest {@Autowiredprivate UserConverter userConverter;@Autowiredprivate EmployeeConverter employeeConverter;@Testpublic void testDto(){User user = new User(1L, "dafei", "666");UserDTO userDTO = userConverter.bean2dto(user);List<UserDTO> userDTOList = userConverter.beans2dtoList(Arrays.asList(new User(2L, "xiaofei", "777")));System.out.println(userDTO);System.out.println(userDTOList);Employee employee = new Employee(1L, "dafei", "666");EmployeeDTO employeeDTO = employeeConverter.bean2dto(employee);List<EmployeeDTO> employeeDTOList = employeeConverter.beans2dtoList(Arrays.asList(new Employee(2L, "xiaofei", "777")));System.out.println(employeeDTO);System.out.println(employeeDTOList);}
}

相关文章:

  • 使用交叉编译工具提示stubs-32.h:7:11: fatal error: gnu/stubs-soft.h: 没有那个文件或目录的解决办法
  • 【LaTex公式】在Latex公式中模拟表格
  • 34、请求处理-【源码分析】-Model、Map原理
  • VulnStack|红日靶场——红队评估四
  • python中将一个列表样式的字符串转换成真正列表的办法以及json.dumps()和 json.loads()
  • SAR ADC 同步逻辑设计
  • 2. 手写数字预测 gui版
  • 声纹技术体系:从理论基础到工程实践的完整技术架构
  • VAE在扩散模型中的技术实现与应用
  • 算法训练第三天
  • 跑步前热身动作
  • Python应用for循环遍历寻b
  • RAGFlow从理论到实战的检索增强生成指南
  • 在win10/11下Node.js安装配置教程
  • Java 认识异常
  • 桥 接 模 式
  • 介绍一种LDPC码译码器
  • uv:现代化的 Python 包和项目管理工具
  • 解常微分方程组
  • GoogLeNet网络模型
  • 世界球队最新排名/优化大师官方正版下载
  • 做网站有哪些软件/成人技能培训机构
  • 淘宝客建网站要钱的吗/百度站长收录入口
  • 网站首页设计模板/什么是网络营销公司
  • 对海尔网站建设水平的评价/河南郑州最新消息
  • p2p网站建设小微金融/app开发公司有哪些