• springboot集成mapstruct快速上手使用【实现DTO和实体间的相互转换】


      

    目录

    前言

    不使用lombok的版本

    导入依赖

    User(实体类) 

    UserDTO(用户传输对象)

    提供转换类型接口 

    测试类 

    使用lombok的版本 

    导入依赖 

    User(用户实体类) 

    UserDTO(用户传输对象) 

     转换的接口

    测试类 

    总结 


    前言

    在我们日常的开发中,会遇到各种DTO或者是VO以及其他的划分,而这些统称为POJO,这些是基于当前业务而衍生出来的类,用来做数据的传输,因此我们都会经历一个必要的阶段,那就是实体类跟DTO或者是其他类型进行一个转换,在我以前接触的项目中发现很多代码是使用get/set来进行转换的,大量的这种冗余代码,看着头都大,比较好的一种方式是使用BeanUtil,但是这种方式也有缺陷,可能会要求变量名一致或者是数据类型一致,要是后期把某个字段的数据类型改了,可能会出现莫名其妙的问题!而mapstruct就是来解决上面所描述的一系列问题!!!

    不使用lombok的版本

    • 导入依赖

    1. <dependency>
    2. <groupId>org.mapstructgroupId>
    3. <artifactId>mapstructartifactId>
    4. <version>1.5.2.Finalversion>
    5. dependency>
    • User(实体类) 

    1. import java.util.Date;
    2. /**
    3. * 用户实体类
    4. *
    5. * @author 小乘字节
    6. * @date 2022/08/02
    7. */
    8. public class User {
    9. /**
    10. * id
    11. */
    12. private Integer id;
    13. /**
    14. * 用户名
    15. */
    16. private String username;
    17. /**
    18. * 创建时间
    19. */
    20. private Date createTime;
    21. /**
    22. * 更新时间
    23. */
    24. private Date updateTime;
    25. public Integer getId() {
    26. return id;
    27. }
    28. public void setId(Integer id) {
    29. this.id = id;
    30. }
    31. public String getUsername() {
    32. return username;
    33. }
    34. public void setUsername(String username) {
    35. this.username = username;
    36. }
    37. public Date getCreateTime() {
    38. return createTime;
    39. }
    40. public void setCreateTime(Date createTime) {
    41. this.createTime = createTime;
    42. }
    43. public Date getUpdateTime() {
    44. return updateTime;
    45. }
    46. public void setUpdateTime(Date updateTime) {
    47. this.updateTime = updateTime;
    48. }
    49. @Override
    50. public String toString() {
    51. return "User{" +
    52. "id=" + id +
    53. ", username='" + username + '\'' +
    54. ", createTime=" + createTime +
    55. ", updateTime=" + updateTime +
    56. '}';
    57. }
    58. }
    • UserDTO(用户传输对象)

    1. /**
    2. * 用户传输对象
    3. *
    4. * @author 小乘字节
    5. * @date 2022/08/02
    6. */
    7. public class UserDTO {
    8. /**
    9. * id
    10. */
    11. private Integer id;
    12. /**
    13. * 用户名
    14. */
    15. private String name;
    16. /**
    17. * 创建时间
    18. */
    19. private String createTime;
    20. /**
    21. * 更新时间
    22. */
    23. private String updateTime;
    24. public Integer getId() {
    25. return id;
    26. }
    27. public void setId(Integer id) {
    28. this.id = id;
    29. }
    30. public String getName() {
    31. return name;
    32. }
    33. public void setName(String name) {
    34. this.name = name;
    35. }
    36. public String getCreateTime() {
    37. return createTime;
    38. }
    39. public void setCreateTime(String createTime) {
    40. this.createTime = createTime;
    41. }
    42. public String getUpdateTime() {
    43. return updateTime;
    44. }
    45. public void setUpdateTime(String updateTime) {
    46. this.updateTime = updateTime;
    47. }
    48. @Override
    49. public String toString() {
    50. return "UserDTO{" + "id=" + id + ", name='" + name + '\'' + ", createTime='" + createTime + '\''
    51. + ", updateTime='" + updateTime + '\'' + '}';
    52. }
    53. }

    注意看User和UserDTO两个类的区别,包含了变量名不一致和数据类型不一致的情况!

    • 提供转换类型接口 

    1. import org.mapstruct.Mapper;
    2. import org.mapstruct.Mapping;
    3. import org.mapstruct.MappingConstants;
    4. import org.mapstruct.Mappings;
    5. import com.ai.dto.UserDTO;
    6. import com.ai.entity.User;
    7. /**
    8. * 用户转换
    9. *
    10. * @author 小乘字节
    11. * @date 2022/08/02
    12. */
    13. @Mapper(componentModel = MappingConstants.ComponentModel.SPRING)
    14. public interface UserConvert {
    15. /**
    16. * User转换UserDTO
    17. *
    18. * @param userDTO 用户dto
    19. * @return {@link User} Mappings是对字段名不一致的字段进行映射
    20. *
    21. * Mapping可以处理变量名不一致映射关系以及指定日期格式等等
    22. */
    23. @Mappings({@Mapping(target = "username", source = "name"),
    24. @Mapping(target = "createTime", dateFormat = "yyyy-MM-dd"),
    25. @Mapping(target = "updateTime", dateFormat = "yyyy-MM-dd")})
    26. User userDtoToUser(UserDTO userDTO);
    27. /**
    28. * UserDTO转换User
    29. *
    30. * @param user 用户
    31. * @return {@link UserDTO}
    32. */
    33. @Mappings({@Mapping(target = "name", source = "username"),
    34. @Mapping(target = "createTime", dateFormat = "yyyy-MM-dd"),
    35. @Mapping(target = "updateTime", dateFormat = "yyyy-MM-dd")})
    36. UserDTO userToUserDto(User user);
    37. }
    • 测试类 

    1. import org.junit.jupiter.api.Test;
    2. import org.springframework.beans.factory.annotation.Autowired;
    3. import org.springframework.boot.test.context.SpringBootTest;
    4. import com.ai.AiApplication;
    5. import com.ai.convert.UserConvert;
    6. import com.ai.dto.UserDTO;
    7. import com.ai.entity.User;
    8. @SpringBootTest(classes = AiApplication.class)
    9. public class UserConvertTest {
    10. @Autowired
    11. private UserConvert userConvert;
    12. @Test
    13. public void m1() {
    14. UserDTO userDTO = new UserDTO();
    15. userDTO.setId(1111);
    16. userDTO.setName("张三");
    17. userDTO.setCreateTime("2020-08-03");
    18. userDTO.setUpdateTime("2020-08-03");
    19. System.out.println("转换前:" + userDTO);
    20. User user = userConvert.userDtoToUser(userDTO);
    21. System.out.println("转换后:" + user);
    22. }
    23. }

    输出结果:

    转换前:UserDTO{id=1111, name='张三', createTime='2020-08-03', updateTime='2020-08-03'}


    转换后:User{id=1111, username='张三', createTime=Mon Aug 03 00:00:00 CST 2020, updateTime=Mon Aug 03 00:00:00 CST 2020} 

    通过打印结果可以看到不管是数据类型不一致又或者是变量名不一致的情况,都能成功的进行转换! 

    那么mapstruct是如何去进行转换的呢?我们提供了一个转换的接口,而这个接口将由mapstruct进行实现,那么我们来借助反编译工具来看下实现类都做了什么处理吧!

    反编译工具: 

    jadx下载地址:点击下载

    jadx源码仓库地址:点击跳转

    找到编译文件内接口的实现类,一般跟接口同包:

    把实现类丢到打开的反编译工具里面,反编译结果如下:

     通过反编译工具可以看得出来本质上还是由get/set来进行的转换,只是这些代码不需要我们手动写了,但是编译后还是会存在!

    使用lombok的版本 

    • 导入依赖 

    很重要:要注意Lombok的版本必须是1.18.16及以上,还需要添加lombok-mapstruct-binding的依赖以使 Lombok 和 MapStruct 一起工作,如果使用的是老版本的Lombok,那么在结合MapStruct使用的过程中会报 xxxx does not have an accessible constructor.的错误!如果要非要适用老版本的Lombok和MapStruct结合适用的话,官网给出的解决方案是:将要由 Lombok 修改的 JavaBean 和要由 MapStruct 处理的映射器接口放入项目的两个单独模块中。

    1. <dependency>
    2. <groupId>org.projectlombokgroupId>
    3. <artifactId>lombokartifactId>
    4. <version>1.18.16version>
    5. <scope>providedscope>
    6. dependency>
    7. <dependency>
    8. <groupId>org.projectlombokgroupId>
    9. <artifactId>lombok-mapstruct-bindingartifactId>
    10. <version>0.2.0version>
    11. dependency>
    12. <dependency>
    13. <groupId>org.mapstructgroupId>
    14. <artifactId>mapstructartifactId>
    15. <version>1.5.2.Finalversion>
    16. dependency>
    • User(用户实体类) 

    1. import lombok.Data;
    2. import java.util.Date;
    3. /**
    4. * 用户实体类
    5. *
    6. * @author 小乘字节
    7. * @date 2022/08/02
    8. */
    9. @Data
    10. public class User {
    11. /**
    12. * id
    13. */
    14. private Integer id;
    15. /**
    16. * 用户名
    17. */
    18. private String username;
    19. /**
    20. * 创建时间
    21. */
    22. private Date createTime;
    23. /**
    24. * 更新时间
    25. */
    26. private Date updateTime;
    27. }
    • UserDTO(用户传输对象) 

    1. import lombok.Data;
    2. /**
    3. * 用户传输对象
    4. *
    5. * @author 小乘字节
    6. * @date 2022/08/02
    7. */
    8. @Data
    9. public class UserDTO {
    10. /**
    11. * id
    12. */
    13. private Integer id;
    14. /**
    15. * 用户名
    16. */
    17. private String name;
    18. /**
    19. * 创建时间
    20. */
    21. private String createTime;
    22. /**
    23. * 更新时间
    24. */
    25. private String updateTime;
    26. }
    •  转换的接口

    1. import org.mapstruct.Mapper;
    2. import org.mapstruct.Mapping;
    3. import org.mapstruct.MappingConstants;
    4. import org.mapstruct.Mappings;
    5. import com.ai.dto.UserDTO;
    6. import com.ai.entity.User;
    7. /**
    8. * 用户转换
    9. *
    10. * @author 小乘字节
    11. * @date 2022/08/02
    12. */
    13. @Mapper(componentModel = MappingConstants.ComponentModel.SPRING)
    14. public interface UserConvert {
    15. /**
    16. * User转换UserDTO
    17. *
    18. * @param userDTO 用户dto
    19. * @return {@link User} Mappings是对字段名不一致的字段进行映射
    20. *
    21. * Mapping可以处理变量名不一致映射关系以及指定日期格式等等
    22. */
    23. @Mappings({@Mapping(target = "username", source = "name"),
    24. @Mapping(target = "createTime", dateFormat = "yyyy-MM-dd"),
    25. @Mapping(target = "updateTime", dateFormat = "yyyy-MM-dd")})
    26. User userDtoToUser(UserDTO userDTO);
    27. /**
    28. * UserDTO转换User
    29. *
    30. * @param user 用户
    31. * @return {@link UserDTO}
    32. */
    33. @Mappings({@Mapping(target = "name", source = "username"),
    34. @Mapping(target = "createTime", dateFormat = "yyyy-MM-dd"),
    35. @Mapping(target = "updateTime", dateFormat = "yyyy-MM-dd")})
    36. UserDTO userToUserDto(User user);
    37. }
    • 测试类 

    1. import org.junit.jupiter.api.Test;
    2. import org.springframework.beans.factory.annotation.Autowired;
    3. import org.springframework.boot.test.context.SpringBootTest;
    4. import com.ai.AiApplication;
    5. import com.ai.convert.UserConvert;
    6. import com.ai.dto.UserDTO;
    7. import com.ai.entity.User;
    8. @SpringBootTest(classes = AiApplication.class)
    9. public class UserConvertTest {
    10. @Autowired
    11. private UserConvert userConvert;
    12. @Test
    13. public void m1() {
    14. UserDTO userDTO = new UserDTO();
    15. userDTO.setId(1111);
    16. userDTO.setName("张三");
    17. userDTO.setCreateTime("2020-08-03");
    18. userDTO.setUpdateTime("2020-08-03");
    19. System.out.println("转换前:" + userDTO);
    20. User user = userConvert.userDtoToUser(userDTO);
    21. System.out.println("转换后:" + user);
    22. }
    23. }

    打印结果:

    转换前:UserDTO(id=1111, name=张三, createTime=2020-08-03, updateTime=2020-08-03)
    转换后:User(id=1111, username=张三, createTime=Mon Aug 03 00:00:00 CST 2020, updateTime=Mon Aug 03 00:00:00 CST 2020) 

    总结 

    想要了解更多可以到官网看看:MapStruct – Java bean mappings, the easy way! 

    官方文档:MapStruct 1.5.2.Final Reference Guide 

    MapStruct仓库:GitHub - mapstruct/mapstruct: An annotation processor for generating type-safe bean mappers 

    在加入了Lombok之后只是简化了实体类,其他地方都没有变,重要的事情说三遍:

    注意Lombok版本号! 注意Lombok版本号!注意Lombok版本号!

    今天就到这里啦~

    🥇原创不易,还希望各位大佬支持一下!
    👍点赞,你的认可是我创作的动力 !
    🌟收藏,你的青睐是我努力的方向!
    ✏️评论,你的意见是我进步的财富!   

  • 相关阅读:
    低市值Pow赛道解析,探寻百倍潜力项目
    Hitters数据集数据分析
    Memento(备忘录模式)
    Discuz3.X各广告位的具体位置和效果探究
    餐饮软件开发价格受到需求的影响!
    关于4diac的发布/订阅和客户端/服务端功能块的思考
    【Python+C#】手把手搭建基于Hugging Face模型的离线翻译系统,并通过C#代码进行访问...
    【store商城项目01】环境准备以及测试
    分析高数值孔径物镜的聚焦特性
    Spring cloud—Netflix
  • 原文地址:https://blog.csdn.net/qq_38238956/article/details/126123665