Java实体映射工具:MapStruct

本文介绍MapStruct的使用方法,包括基本配置、Spring注入、自定义映射、集合映射、多参数映射等高级功能,以及如何处理默认值、常量和空Model返回。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

        MapStruct版本:1.3.1.Final。


        当我们需要进行Java Model之间的拷贝时,或者项目要求Java Model需要严格区分为数据对象(DO)、数据传输对象(DTO)和展示对象(VO)的时候,我们就不得不把一个实体中的属性映射到另一个实体中。最简单的做法就是写一个工具类,进行不断的getter / setter,这样虽然能完成要求但却写了很多冗余代码,维护起来相当恶心。所以这个时候就需要一款能自动映射实体属性的工具了。

        Spring自带的BeanUtils工具类算是一款,但是它却不能自定义映射规则;ModelMapper也是一款映射工具框架,虽然它可以自定义映射规则,但写法上却复杂一些。而MapStruct作为一款优秀的Java实体映射工具来说,它也能够自定义映射规则,并且是通过注解的方式来实现的,源和目标看得很清楚明白。不同于BeanUtils和ModelMapper是通过反射在运行期生成代码从而导致性能不高,MapStruct是在编译期生成实现类映射代码,生成的代码就是普通的getter / setter代码,和原生使用的性能相差不大。


1 简单使用

        首先需要引入的依赖如下所示:

<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>
</dependency>

        除此之外如果使用的IDE是idea的话,还可以下载MapStruct的插件:

        该插件可以动态地提示当前没有进行映射的字段,以及其他一些对MapStruct的支持(和Lombok不同,该插件不是必须安装的)。

        接着准备两个Java Model如下所示,一个DO,一个VO:

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;

@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class PersonDO implements Serializable {

    private static final long serialVersionUID = -3483764417202514211L;

    private Long personId;

    private String name;

    private Integer sex;

    private Integer age;

    private String address;
}
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;

@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class PersonVO implements Serializable {

    private static final long serialVersionUID = 7827081422917080855L;

    private Long id;

    private String name;

    private String sex;

    private Integer age;

    private String address;
}

        其中用到了Lombok的注解来简化编程,详见我的另一篇文章《Lombok概述》。在完成了上述准备之后,就可以进行MapStruct的开发使用了。

        我们现在是要把PersonDO转成PersonVO,首先需要写一个接口,如下所示:

import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;

@Mapper
public interface PersonMapper {

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

    PersonVO personDO2VO(PersonDO personDO);
}

        之后需要进行打包编译,在对属性进行变动后都要进行打包编译,以此来生成新的实现类。MapStruct并不能及时地反映出属性的变更,比方说接口提供方变更了Model的属性,而调用方只有等到打包编译的时候才能提示出错误,这也许是MapStruct为数不多的缺点了吧,但介于MapStruct是在编译期生成映射代码的机制,这点也无可厚非,只要多加留意即可。

        生成的实现类如下所示:

import javax.annotation.Generated;

@Generated(
    value = "org.mapstruct.ap.MappingProcessor",
    date = "2020-02-08T18:46:28+0800",
    comments = "version: 1.3.1.Final, compiler: javac, environment: Java 1.8.0_201 (Oracle Corporation)"
)
public class PersonMapperImpl implements PersonMapper {

    @Override
    public PersonVO personDO2VO(PersonDO personDO) {
        if ( personDO == null ) {
            return null;
        }

        PersonVO personVO = new PersonVO();

        personVO.setName( personDO.getName() );
        if ( personDO.getSex() != null ) {
            personVO.setSex( String.valueOf( personDO.getSex() ) );
        }
        personVO.setAge( personDO.getAge() );
        personVO.setAddress( personDO.getAddress() );

        return personVO;
    }
}

        由上可以看到,生成的实现类就是通过getter / setter方法来实现的,不损失性能。由此可见我们只需要写一个接口,并定义好映射规则的方法就行了,不需要再写其他的代码。相应的测试代码如下所示:

PersonDO personDO = PersonDO.builder().personId(1L).name("Robert Hou").sex(1).age(24).address("Beijing").build();
PersonVO personVO = PersonMapper.INSTANCE.personDO2VO(personDO);
System.out.println(personVO);

        运行结果如下:

PersonVO(id=null, name=Robert Hou, sex=1, age=24, address=Beijing)

2 Spring注入

        除了上节的在PersonMapper映射接口中声明INSTANCE的方式来进行调用之外,MapStruct也同时支持Spring的依赖注入机制,如下所示:


                
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值