MapStruct 超好用的Java实体映射工具

前言

MapStruct入门笔记,取代BeanUtils.copy(source,target)

官网地址:
https://mapstruct.org/

官网文档:

https://mapstruct.org/documentation/reference-guide/
在这里插入图片描述选择相应版本 HTML 或 PDF 形式文档查看即可。

V1.2.0 HTML地址:
https://mapstruct.org/documentation/1.2/reference/html/

一、准备工作

添加maven依赖

我第一次用的是1.3.1版本,但是插件不可用,降级尝试1.2.0,完美。

...
<properties>
    <org.mapstruct.version>1.2.0.Final</org.mapstruct.version>
</properties>
...
<dependencies>
    <dependency>
        <groupId>org.mapstruct</groupId>
        <artifactId>mapstruct-jdk8</artifactId>
        <version>${org.mapstruct.version}</version>
    </dependency>
</dependencies>
...
<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.5.1</version>
            <configuration>
                <source>1.8</source>
                <target>1.8</target>
                <annotationProcessorPaths>
                    <path>
                        <groupId>org.mapstruct</groupId>
                        <artifactId>mapstruct-processor</artifactId>
                        <version>${org.mapstruct.version}</version>
                    </path>
                </annotationProcessorPaths>
            </configuration>
        </plugin>
    </plugins>
</build>
...

二、入门,创建简单的映射

1,先创建映射接口

官网上是:

To create a mapper simply define a Java interface with the required
mapping method(s) and annotate it with the org.mapstruct.Mapper annotation

在这里引用官网的栗子

@Mapper
public interface CarMapper {

    @Mappings({
        @Mapping(source = "make", target = "manufacturer"),
        @Mapping(source = "numberOfSeats", target = "seatCount")
        @Mapping(target = "name", ignore = true)
    })
    CarDto carToCarDto(Car car);

    @Mapping(source = "name", target = "fullName")
    PersonDto personToPersonDto(Person person);
}

需要注意的是,

1,@Mapper 注解,表示MapStruct要会去实现该接口
1,@Mapping 有多个时,需要使用@Mappings(),否则会报错,如下

在这里插入图片描述

2,如果source对象中属性与target对象中属性字段名一致,会自动映射对应属性,而不需要@Mapping指定。如果不一致则需要指定。
3,如果有某个属性不想映射,可以加 ignore=true
4,类型转换
4.1 int 转 String

@Mapper
public interface CarMapper {

    @Mapping(source = "price", numberFormat = "$#.00")
    CarDto carToCarDto(Car car);

    @IterableMapping(numberFormat = "$#.00")
    List<String> prices(List<Integer> prices);
}

4.2 BigDecimal 转 String

@Mapper
public interface CarMapper {

    @Mapping(source = "power", numberFormat = "#.##E0")
    CarDto carToCarDto(Car car);

}

4.3 date 转 String 指定格式

@Mapper
public interface CarMapper {

    @Mapping(source = "manufacturingDate", dateFormat = "dd.MM.yyyy")
    CarDto carToCarDto(Car car);

    @IterableMapping(dateFormat = "dd.MM.yyyy")
    List<String> stringListToDateList(List<Date> dates);
}

2,检查映射是否生效

在执行程序或插件compiler后,检查是否有自动生成的一个implement实现接口CarMapper,这个文件在target目录下,最快的方式是全局搜索CarMapper,定位CarMapperImpl。如果此文件存在,表示映射可用。

如果在执行程序或compiler插件的过程中build failure,需要先解决问题啦。我遇到的问题以及解决方法将在下一篇笔记汇总。

官网上是:

The @Mapper annotation causes the MapStruct code generator to create
an implementation of the CarMapper interface during build-time.

自动生成的代码如下:

public class CarMapperImpl implements CarMapper {

    @Override
    public CarDto carToCarDto(Car car) {
        if ( car == null ) {
            return null;
        }

        CarDto carDto = new CarDto();

        if ( car.getFeatures() != null ) {
            carDto.setFeatures( new ArrayList<String>( car.getFeatures() ) );
        }
        carDto.setManufacturer( car.getMake() );
        carDto.setSeatCount( car.getNumberOfSeats() );
        carDto.setDriver( personToPersonDto( car.getDriver() ) );
        carDto.setPrice( String.valueOf( car.getPrice() ) );
        if ( car.getCategory() != null ) {
            carDto.setCategory( car.getCategory().toString() );
        }
        carDto.setEngine( engineTtoEngineDto( car.getEngine() ) );

        return carDto;
    }

    @Override
    public PersonDto personToPersonDto(Person person) {
        //...
    }

    private EngineDto engineToEngineDto(Engine engine) {
        if ( engine == null ) {
            return null;
        }

        EngineDto engineDto = new EngineDto();

        engineDto.setHorsePower(engine.getHorsePower());
        engineDto.setFuel(engine.getFuel());

        return engineDto;
    }
}

三、实战

映射添加好了,接下来怎么用呢?
继续看文档,文档中提到两种方式,一种是使用Mappers Factory(默认),一种是使用依赖注入

1. The Mappers Factory

1,声明一个映射接口

@Mapper
public interface CarMapper {

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

    CarDto carToCarDto(Car car);
}

Or

声明一个抽象的映射接口 (1.3.1版本支持)

@Mapper
public abstract class CarMapper {

    public static final CarMapper INSTANCE = Mappers.getMapper( CarMapper.class );

    CarDto carToCarDto(Car car);
}

然后在service层就可以调用了

Car car = ...;
CarDto dto = CarMapper.INSTANCE.carToCarDto( car );

2.Using dependency injection

在映射接口上注解@Mapper后添加属性componentModel,与Spring框架结合,所以我在代码中添加@Mapper(componentModel=“spring”),下面是官网中的栗子

@Mapper(componentModel = "cdi")
public interface CarMapper {

    CarDto carToCarDto(Car car);
}

在service层,使用@Autowired就可以注入,

@Autowired
private CarMapper mapper;

在官网中,给出的栗子是这样的:

@Inject
private CarMapper mapper;

并且启动程序会发现,在自动生成的代码中,也就是在接口的实现类上会自动生成注解 @Component

@Component
public class ThirlDtoMapperImpl implements ThirlDtoMapper {
	... ...
}

end

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值