Java高性能实体类转换工具MapStruct的使用教程详解

 更新时间:2024年03月24日 10:02:06   作者:EvenBoy  
MapStruct 是一个代码生成器,它基于约定优于配置的方法,极大地简化了 Java bean 类型之间的映射实现,本文主要介绍了MapStruct的具体使用以及如何进行实体类转换,感兴趣的可以了解下

MapStruct

它是什么?

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

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

为什么?

多层应用程序通常需要在不同的对象模型(例如实体和 DTO)之间进行映射。编写这样的映射代码是一项乏味且容易出错的任务。MapStruct 旨在通过尽可能地自动化来简化这项工作。

与其他映射框架相比,MapStruct 在编译时生成 bean 映射,这确保了高性能,允许快速的开发人员反馈和彻底的错误检查。

如何?

MapStruct 是一个注解处理器,它插入到 Java 编译器中,可用于命令行构建(Maven、Gradle 等)以及您首选的 IDE。

MapStruct 使用合理的默认值,但在配置或实现特殊行为时会采取措施。

使用场景

1、数据库中的字段和你对接的A部门、B部门的入参字段不一致的情况。

2、涉及到一些入参和出参值的转换 比如:性别、日期等。

使用教程

1、引入pom.xml

     <!--mapStruct依赖-->
        <dependency>
            <groupId>org.mapstruct</groupId>
            <artifactId>mapstruct</artifactId>
            <version>1.3.1.Final</version>
        </dependency>
        <dependency>
            <groupId>org.mapstruct</groupId>
            <artifactId>mapstruct-processor</artifactId>
            <version>1.3.1.Final</version>
            <scope>provided</scope>
        </dependency>

2、入参(每个部门的入参可能不太一样)

package com.lezu.springboot.common.dto.param;
 
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
 
/**
 * @author LianJiaYu
 * @date 2022/9/1 14:09
 */
@Data
public class UserInfoParam {
 
    @ApiModelProperty(value = "用户账号")
    private String account;
 
    @ApiModelProperty(value = "性别")
    private String gender;
 
    @ApiModelProperty(value = "密码")
    private String password;
 
    @ApiModelProperty(value = "出生日期")
    private Long birthday;
 
    @ApiModelProperty(value = "验证码captchaId")
    private String captchaId;
 
    @ApiModelProperty(value = "昵称")
    private String name;
 
    @ApiModelProperty(value = "验证码")
    private String code;
 
}

3、对应数据库中的字段

package com.lezu.springboot.common.dto.in;
 
import com.lezu.springboot.common.Page;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
 
import javax.validation.constraints.NotNull;
import java.io.Serializable;
import java.util.Date;
 
/**
 * @Author LianJiaYu
 * @Date 2021/4/4 22:06
 * @Version 1.0
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
public class InUserInfoDto extends Page implements Serializable {
 
    private static final long serialVersionUID = 5755742614532104337L;
 
    @ApiModelProperty(value = "用户账号")
    @NotNull(message = "用户名不能为空")
    private String username;
 
    @ApiModelProperty(value = "性别")
    private Integer gender;
 
    @ApiModelProperty(value = "密码")
    @NotNull(message = "密码不能为空")
    private String password;
 
    @ApiModelProperty(value = "出生日期")
    private Date birthday;
 
    @ApiModelProperty(value = "验证码captchaId")
    private String captchaId;
 
    @ApiModelProperty(value = "昵称")
    private String name;
 
    @ApiModelProperty(value = "验证码")
    private String code;
 
    @ApiModelProperty(value = "默认状态")
    private String defaultStatus;
 
}

4、定义工厂

package com.lezu.springboot.common.dto.Interface;
 
import com.lezu.springboot.common.ListResult;
import com.lezu.springboot.common.conversion.DataConversionWorker;
import com.lezu.springboot.common.conversion.EnumConversionWorker;
import com.lezu.springboot.common.dto.in.InUserInfoDto;
import com.lezu.springboot.common.dto.out.OutUserInfoDto;
import com.lezu.springboot.common.dto.param.UserInfoParam;
import com.lezu.springboot.common.dto.result.UserInfoResult;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Mappings;
import org.mapstruct.factory.Mappers;
 
/**
 * @author LianJiaYu
 * @date 2022/9/1 14:04
 */
@Mapper(uses = {DataConversionWorker.class, EnumConversionWorker.class})
public interface UserConvert {
    UserConvert INSTANCE = Mappers.getMapper(UserConvert.class);
 
 
    //入参转换
    @Mappings({
            @Mapping(source = "account", target = "username"),
            @Mapping(source = "gender", target = "gender", qualifiedByName = "setGenderToInteger"),
            @Mapping(source = "birthday", target = "birthday", qualifiedByName = "getBirthdayToDate"),
            @Mapping(target = "defaultStatus", defaultValue = "success"),
    })
    InUserInfoDto userInfoConvert(UserInfoParam param);
 
 
    //出参转换
    @Mappings({
            @Mapping(source = "username", target = "account"),
            @Mapping(source = "gender", target = "gender", qualifiedByName = "setGenderToString"),
            @Mapping(source = "birthday", target = "birthday", qualifiedByName = "getBirthdayToLong"),
    })
    UserInfoResult userInfoResultConvert(OutUserInfoDto dto);
 
    ListResult<UserInfoResult> listUserInfoResultConvert(ListResult<OutUserInfoDto> list);
 
 
}

5、定义时间戳转换日期和日期转时间戳方法

package com.lezu.springboot.common.conversion;
 
import cn.hutool.core.date.DateUtil;
import org.mapstruct.Named;
 
import java.util.Date;
 
/**
 * @author LianJiaYu
 * @date 2022/9/2 15:08
 */
//@Component
public class DataConversionWorker {
 
    @Named("getBirthdayToDate")
    public Date getBirthdayToDate(Long birthday) {
        if (birthday == null) {
            return null;
        }
        return DateUtil.date(birthday);
    }
 
    @Named("getBirthdayToLong")
    public Long getBirthdayToLong(Date birthday) {
        if (birthday == null) {
            return null;
        }
        return birthday.getTime();
    }
}

6、定义性别转换方法

package com.lezu.springboot.common.conversion;
 
import com.lezu.springboot.enums.UserGenderEnum;
import org.mapstruct.Named;
import org.springframework.stereotype.Component;
 
/**
 * @author LianJiaYu
 * @date 2022/9/2 15:08
 */
//@Component
public class EnumConversionWorker {
 
    @Named("setGenderToInteger")
    public Integer setGenderToInteger(String type) {
        return UserGenderEnum.getByType(type).getCode();
    }
 
    @Named("setGenderToString")
    public Integer setGenderToString(Integer code) {
        return UserGenderEnum.getByCode(code).getCode();
    }
 
}

7、性别转换枚举

package com.lezu.springboot.enums;
 
/**
 * @author LianJiaYu
 * @date 2022/9/16 10:10
 */
public enum UserGenderEnum {
    FEMALE(0, "female"),
    MALE(1, "male"),
    UNKNOWN(2, "unknown"),
    ;
 
 
    private Integer code;
    private String type;
 
    UserGenderEnum(Integer code, String type) {
        this.code = code;
        this.type = type;
    }
 
    public Integer getCode() {
        return code;
    }
 
    public String getType() {
        return type;
    }
 
 
    public static UserGenderEnum getByCode(Integer code) {
        for (UserGenderEnum v : UserGenderEnum.values()) {
            if (v.getCode() == code) {
                return v;
            }
        }
        return UNKNOWN;
    }
 
    public static UserGenderEnum getByType(String type) {
        for (UserGenderEnum v : UserGenderEnum.values()) {
            if (v.getType().equals(type)) {
                return v;
            }
        }
        return UNKNOWN;
    }
}

8、编写Controller代码进行测试

package com.lezu.springboot.controller;
 
import com.alibaba.fastjson.JSON;
import com.lezu.springboot.common.ListResult;
import com.lezu.springboot.common.dto.Interface.UserConvert;
import com.lezu.springboot.common.dto.in.InUserInfoDto;
import com.lezu.springboot.common.dto.param.UserInfoParam;
import com.lezu.springboot.common.dto.result.UserInfoResult;
import com.lezu.springboot.enums.ResultEnum;
import com.lezu.springboot.service.UserInfoHandleService;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
 
import java.util.Objects;
 
/**
 * 高性能实体类转换工具MapStruct
 * 类型转换工具
 * @author LianJiaYu
 * @date 2022/9/1 13:57
 */
@RestController
@RequestMapping("/mapstruct")
@Slf4j
public class MapstructController {
 
    @Autowired
    private UserInfoHandleService userInfoHandleService;
 
    @ApiOperation("类型转换")
    @PostMapping("/login")
    public ListResult<UserInfoResult> login(UserInfoParam params) {
        ListResult listResult = new ListResult();
        if (Objects.isNull(params)) {
            return listResult.build(ResultEnum.PARAM_ERROR.getCode(), ResultEnum.PARAM_ERROR.getMsg());
        }
        //入参-日志
        log.info("params:" + JSON.toJSONString(params));
 
        //入参-参数转换
        InUserInfoDto inDto = UserConvert.INSTANCE.userInfoConvert(params);
        log.info("inDto:" + JSON.toJSONString(inDto));
 
 
        //出参-参数转换
        listResult = UserConvert.INSTANCE.outDtoToResult(userInfoHandleService.listByPage(inDto));
        log.info("listResult:" + JSON.toJSONString(listResult));
        return listResult;
    }
}

Service层

   @Override
    public ListResult listByPage(InUserInfoDto inDto) {
        ListResult listResult = new ListResult();
        LambdaQueryWrapper<UserInfo> wrapper = Wrappers.lambdaQuery();
        if (StrUtil.isNotBlank(inDto.getUsername())) {
            wrapper.like(UserInfo::getUsername, inDto.getUsername());
        }
        int pageNum = inDto.getPageNum();
        int pageSize = inDto.getPageSize() == 0 ? 10 : inDto.getPageSize();
 
        IPage<UserInfo> page = new Page<>(pageNum, pageSize);
        userInfoService.page(page, wrapper);
        List<OutUserInfoDto> list = page.getRecords().stream().map(v -> {
            OutUserInfoDto dto = new OutUserInfoDto();
            BeanUtils.copyProperties(v, dto);
            return dto;
        }).collect(Collectors.toList());
 
 
        return listResult.ok(list, page.getTotal());
    }

OutUserInfo实体类

package com.lezu.springboot.common.dto.out;
 
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
 
import java.io.Serializable;
 
/**
 * @Author LianJiaYu
 * @Date 2021/4/4 22:06
 * @Version 1.0
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
public class OutUserInfoDto implements Serializable {
 
    private static final long serialVersionUID = 6248490570574329534L;
 
    @ApiModelProperty(value = "主键id")
    @TableId(value = "id", type = IdType.AUTO)
    private Integer id;
 
    @ApiModelProperty(value = "用户账号")
    private String username;
 
    @ApiModelProperty(value = "性别")
    private String gender;
 
    @ApiModelProperty(value = "密码")
    private String password;
 
    @ApiModelProperty(value = "权限")
    private Integer power;
 
    @ApiModelProperty(value = "昵称")
    private String name;
 
 
 
}

以上就是Java高性能实体类转换工具MapStruct的使用教程详解的详细内容,更多关于Java MapStruct实体类转换的资料请关注脚本之家其它相关文章!

相关文章

  • idea中git如何删除commit提交的log信息

    idea中git如何删除commit提交的log信息

    这篇文章主要介绍了idea中git如何删除commit提交的log信息问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-07-07
  • servlet异步请求的实现

    servlet异步请求的实现

    本文主要介绍了servlet异步请求的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-07-07
  • Java如何实现密码加密

    Java如何实现密码加密

    这篇文章主要介绍了Java如何实现密码加密,帮助大家更好的理解和学习java,感兴趣的朋友可以了解下
    2020-08-08
  • 详解MyBatis特性之动态SQL

    详解MyBatis特性之动态SQL

    动态 SQL 是 MyBatis 的强大特性之一,这篇文章我们将结合动态SQL完成更加复杂的 SQL 操作,文章通过代码示例给大家介绍的非常详细,对大家的学习或工作有一定的帮助,需要的朋友可以参考下
    2024-01-01
  • 解决shiro 定时监听器不生效的问题 onExpiration不调用问题

    解决shiro 定时监听器不生效的问题 onExpiration不调用问题

    这篇文章主要介绍了解决shiro 定时监听器不生效的问题 onExpiration不调用问题。具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-07-07
  • springboot项目中mybatis-plus@Mapper注入失败问题

    springboot项目中mybatis-plus@Mapper注入失败问题

    这篇文章主要介绍了springboot项目中mybatis-plus@Mapper注入失败问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-07-07
  • Spring boot2X负载均衡和反向代理实现过程解析

    Spring boot2X负载均衡和反向代理实现过程解析

    这篇文章主要介绍了Spring boot2X负载均衡和反向代理实现过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-12-12
  • Java 读取指定路径的文本文件并返回String的方法

    Java 读取指定路径的文本文件并返回String的方法

    今天小编就为大家分享一篇Java 读取指定路径的文本文件并返回String的方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-07-07
  • Java面试题冲刺第十八天--Spring框架3

    Java面试题冲刺第十八天--Spring框架3

    这篇文章主要为大家分享了最有价值的三道关于Spring框架的面试题,涵盖内容全面,包括数据结构和算法相关的题目、经典面试编程题等,感兴趣的小伙伴们可以参考一下
    2021-08-08
  • java实现多选批量删除功能

    java实现多选批量删除功能

    工作中批量删除可以提高我们的工作效率,今天这篇文章主要介绍了java实现多选批量删除功能,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-08-08

最新评论