MapStruct入门使用

背景

在实际的项目开发中会大量的使用POJO作为数据载体,通常有如下的:

实体名实体含义说明
DOData Object与数据库表结构一一对应,通过DAO层向上传输数据源对象
DTOData Transfer Object数据传输对象,Service或Manager向外传输的对象
BOBusiness Object业务对象,由Service层输出的封装业务逻辑的对象
VOView Object显示层对象,通常是 Web 向模板渲染引擎层传输的对象
  • Spring BeanUtils
  • Apache BeanUtils
  • Orika的MapperFacade和MapperFactory
  • MapStruct
    可以选择MapStruct,功能十分强大,而且很灵活,可以满足我们需要的各种需求。

入门案例

Maven项目引入

只需要在pom.xml文件中加入以下依赖即可:

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

源对象

在这里插入图片描述

CarDO

package com.linfanchen.springboot.lab.mapstruct.domain;

public class CarDO {
    /**
     * 主键ID
     */
    private Integer id;

    /**
     * 名称
     */
    private String name;

    /**
     * 品牌
     */
    private String brand;

    /**
     * 车价
     */
    private Integer price;

    /**
     * 轮胎属性
     */
    private TyreDO tyreDO;

    /**
     * 汽车图片
     */
    private String images;

    public String getImages() {
        return images;
    }

    public void setImages(String images) {
        this.images = images;
    }

    public TyreDO getTyreDO() {
        return tyreDO;
    }

    public void setTyreDO(TyreDO tyreDO) {
        this.tyreDO = tyreDO;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getBrand() {
        return brand;
    }

    public void setBrand(String brand) {
        this.brand = brand;
    }

    public Integer getPrice() {
        return price;
    }

    public void setPrice(Integer price) {
        this.price = price;
    }
}

TyreDO

package com.linfanchen.springboot.lab.mapstruct.domain;

/**
 * 轮胎
 */
public class TyreDO {
    /**
     * 主键ID
     */
    private Integer id;

    /**
     * 轮胎名称
     */
    private String name;

    /**
     * 轮胎尺寸
     */
    private Integer size;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getSize() {
        return size;
    }

    public void setSize(Integer size) {
        this.size = size;
    }
}

目标对象

CarBO

package com.linfanchen.springboot.lab.mapstruct.bo;

import com.linfanchen.springboot.lab.mapstruct.domain.TyreDO;

import java.util.List;

/**
 * 汽车业务对象
 */
public class CarBO {
    /**
     * 主键ID
     */
    private Integer id;

    /**
     * 名称
     */
    private String name;

    /**
     * 品牌
     */
    private String brand;

    /**
     * 车价
     */
    private Integer price;

    /**
     * 轮胎属性
     */
    private TyreDO tyreDO;

    /**
     * 汽车图片
     */
    private String images;


    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getBrand() {
        return brand;
    }

    public void setBrand(String brand) {
        this.brand = brand;
    }

    public Integer getPrice() {
        return price;
    }

    public void setPrice(Integer price) {
        this.price = price;
    }

    public TyreDO getTyreDO() {
        return tyreDO;
    }

    public void setTyreDO(TyreDO tyreDO) {
        this.tyreDO = tyreDO;
    }

    public String getImages() {
        return images;
    }

    public void setImages(String images) {
        this.images = images;
    }
}

CarDetailBO

package com.linfanchen.springboot.lab.mapstruct.bo;

import com.linfanchen.springboot.lab.mapstruct.domain.TyreDO;

import java.util.List;

/**
 * 汽车业务对象
 */
public class CarDetailBO {
    /**
     * 主键ID
     */
    private Integer carId;

    /**
     * 名称
     */
    private String carName;

    /**
     * 品牌
     */
    private String carBrand;

    /**
     * 车价
     */
    private Integer price;

    /**
     * 轮胎属性
     */
    private TyreDO tyreDetail;

    /**
     * 汽车图片
     */
    private List<String> images;


    public Integer getCarId() {
        return carId;
    }

    public void setCarId(Integer carId) {
        this.carId = carId;
    }

    public String getCarName() {
        return carName;
    }

    public void setCarName(String carName) {
        this.carName = carName;
    }

    public String getCarBrand() {
        return carBrand;
    }

    public void setCarBrand(String carBrand) {
        this.carBrand = carBrand;
    }

    public Integer getPrice() {
        return price;
    }

    public void setPrice(Integer price) {
        this.price = price;
    }

    public TyreDO getTyreDetail() {
        return tyreDetail;
    }

    public void setTyreDetail(TyreDO tyreDetail) {
        this.tyreDetail = tyreDetail;
    }

    public List<String> getImages() {
        return images;
    }

    public void setImages(List<String> images) {
        this.images = images;
    }
}

转换器 CarConvert

说明:

  • INSTANCE 是MapStruct为我们提供的映射工厂,指定接口类型后自动帮我们创建接口的实现,且保证是线程安全的单例,无需自己手动创建。
package com.linfanchen.springboot.lab.mapstruct.convert;

import com.linfanchen.springboot.lab.mapstruct.bo.CarBO;
import com.linfanchen.springboot.lab.mapstruct.bo.CarDetailBO;
import com.linfanchen.springboot.lab.mapstruct.domain.CarDO;
import org.apache.commons.lang3.StringUtils;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Mappings;
import org.mapstruct.Named;
import org.mapstruct.factory.Mappers;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * 转换类
 */
@Mapper
public interface CarConvert {

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

    /**
     * 来源和目标类的直接转换
     */
    CarBO convert(CarDO carDO);

    /**
     * 添加字段处理和映射关系后的转换
     */
    @Mappings({
            @Mapping(source = "id", target = "carId"),
            @Mapping(source = "name", target = "carName"),
            @Mapping(source = "brand", target = "carBrand"),
            @Mapping(source = "tyreDO.id", target = "tyreDetail.id"),
            @Mapping(source = "tyreDO.name", target = "tyreDetail.name"),
            @Mapping(source = "tyreDO.size", target = "tyreDetail.size"),
            @Mapping(source = "images", target = "images", qualifiedByName = "convertImagesStrToList")

    })
    CarDetailBO convertDetail(CarDO carDO);

    @Named("convertImagesStrToList")
    default List<String> convertImagesStrToList(String images) {
        String[] splitArr = org.springframework.util.StringUtils.split(images, ",");
        return new ArrayList<>(Arrays.asList(splitArr));
    }

}

使用 CarTest

package com.linfanchen.springboot.lab.mapstruct;

import com.linfanchen.springboot.lab.mapstruct.bo.CarBO;
import com.linfanchen.springboot.lab.mapstruct.bo.CarDetailBO;
import com.linfanchen.springboot.lab.mapstruct.convert.CarConvert;
import com.linfanchen.springboot.lab.mapstruct.domain.CarDO;
import com.linfanchen.springboot.lab.mapstruct.domain.TyreDO;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

@RunWith(SpringRunner.class)
@SpringBootTest
public class CarTest {

    @Test
    public void test() {
        // 创建轮胎对象
        TyreDO tyreDO = new TyreDO();
        tyreDO.setId(888);
        tyreDO.setName("米其林245/45R19");
        tyreDO.setSize(19);

        // 汽车图片地址,通过半角逗号分隔的http地址
        List<String> imageList = new ArrayList<>();
        imageList.add("https://www.bmw.com.cn/image.1601043751651.jpg");
        imageList.add("https://www.bmw.com.cn/image.1623295725814.jpg");
        imageList.add("https://www.bmw.com.cn/image.1611042489480.jpg");
        String imageStr = imageList.stream().map(String::valueOf).collect(Collectors.joining(","));

        // 创建汽车对象
        CarDO carDO = new CarDO();
        carDO.setId(123);
        carDO.setBrand("BMW");
        carDO.setName("宝马530Li行政版");
        carDO.setPrice(540000);
        carDO.setTyreDO(tyreDO);
        carDO.setImages(imageStr);

        // 直接的数据拷贝
        CarBO carBO = CarConvert.INSTANCE.convert(carDO);
        System.out.println(carBO.getImages());
        System.out.println(carBO.getBrand());
        System.out.println(carBO.getName());
        System.out.println(carBO.getTyreDO());

        // 带数据转换的拷贝
        CarDetailBO carDetailBO = CarConvert.INSTANCE.convertDetail(carDO);
        System.out.println(carDetailBO.getImages());
        System.out.println(carDetailBO.getTyreDetail().getName());
    }

}

总结

在需要进行对象的转换的时候,我们可以使用MapStruct进行各种灵活的转换,最终得到我们想要的数据。

参考文档:

官方文档

MapStruct使用指南

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值