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实体类转换的资料请关注脚本之家其它相关文章!

相关文章

  • 解析Java中所有错误和异常的父类java.lang.Throwable

    解析Java中所有错误和异常的父类java.lang.Throwable

    这篇文章主要介绍了Java中所有错误和异常的父类java.lang.Throwable,文章中简单地分析了其源码,说明在代码注释中,需要的朋友可以参考下
    2016-03-03
  • 浅谈java web中常用对象对应的实例化接口

    浅谈java web中常用对象对应的实例化接口

    下面小编就为大家带来一篇浅谈java web中常用对象对应的实例化接口。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-02-02
  • SpringBoot整合Mybatis Plus实现基本CRUD的示例代码

    SpringBoot整合Mybatis Plus实现基本CRUD的示例代码

    Mybatis Plus是在Mybatis的基础上的增强,使得我们对一些基本的CRUD使用起来更方便,本文主要介绍了SpringBoot整合Mybatis Plus实现基本CRUD的示例代码,具有一定的参考价值,感兴趣的可以了解一下
    2023-05-05
  • java Long类型转为String类型的两种方式及区别说明

    java Long类型转为String类型的两种方式及区别说明

    这篇文章主要介绍了java Long类型转为String类型的两种方式及区别说明,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-09-09
  • Spring Security十分钟入门教程

    Spring Security十分钟入门教程

    这篇文章主要介绍了Spring Security入门教程,Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架
    2022-09-09
  • 图文讲解IDEA中根据数据库自动生成实体类

    图文讲解IDEA中根据数据库自动生成实体类

    这篇文章主要以图文讲解IDEA中根据数据库自动生成实体类,本文主要以Mysql数据库为例,应该会对大家有所帮助,如果有错误的地方,还望指正
    2023-03-03
  • SpringBoot 请求参数忽略大小写的实例

    SpringBoot 请求参数忽略大小写的实例

    这篇文章主要介绍了SpringBoot 请求参数忽略大小写的实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-01-01
  • Java中的代理模式详解及实例代码

    Java中的代理模式详解及实例代码

    这篇文章主要介绍了Java中的代理模式详解及实例代码的相关资料,这里附有实例代码,需要的朋友可以参考下
    2017-02-02
  • Java关键字super超详细解释

    Java关键字super超详细解释

    在Java中super是一个关键字,用于访问父类中的属性、方法或构造函数,这篇文章主要给大家介绍了关于Java关键字super超详细解释的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2023-11-11
  • Java分治法与二分搜索算法实例分析

    Java分治法与二分搜索算法实例分析

    这篇文章主要介绍了Java分治法与二分搜索算法,简单讲述了分治法与二分搜索算法的原理并结合java实例分析了二分搜索算法的实现与使用技巧,需要的朋友可以参考下
    2017-11-11

最新评论