DO转DTO映射MapStruct生产环境使用

什么是MapStruct?

MapStruct是用于生成类型安全的bean映射类的Java注解处理器。

你所要做的就是定义一个映射器接口,声明任何需要映射的方法。在编译过程中,MapStruct将生成该接口的实现。此实现使用纯Java的方法调用源对象和目标对象之间进行映射,并非Java反射机制。

与手工编写映射代码相比,MapStruct通过生成冗长且容易出错的代码来节省时间。在配置方法的约定之后,MapStruct使用了合理的默认值,但在配置或实现特殊行为时将不再适用。

与动态映射框架相比,MapStruct具有以下优点:

1,使用纯Java方法代替Java反射机制快速执行
2,编译时类型安全:只能映射彼此的对象和属性,不能映射一个Order实体到一个Customer DTO中等等
3,如果无法映射实体或属性,则在编译时清除错误报告

maven依赖导入

<dependency>
            <groupId>org.mapstruct</groupId>
            <artifactId>mapstruct</artifactId>
            <version>1.3.1.Final</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>org.mapstruct</groupId>
            <artifactId>mapstruct-processor</artifactId>
            <version>1.3.1.Final</version>
            <scope>compile</scope>
        </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>
                </configuration>
            </plugin>
        </plugins>
    </build>

直接上代码

首先定义一个泛型的基础映射器BaseMapping

/**
 * <p>
 * MapStruct映射基类,直接继承接口即可使用通用方法,针对性指定需在继承类的接口方法上指定
 *
 * 例: public interface xxxMapping extends BaseMapping<xxxDO, xxxDTO>
 *
 * 具体用法可参考单元测试,建议配合MapStruct Support插件使用
 */
@MapperConfig(componentModel = "spring")
public interface BaseMapping<S, T> {

    /** 正向映射 */
    @InheritConfiguration
    T convertTo(S obj);

    /** 反向映射 */
    @InheritInverseConfiguration(name = "convertTo")
    S convertFrom(T obj);

    /** 正向映射(List) */
    default List<T> convertTo(List<S> list) {
        if (list == null) {
            return null;
        }

        List<T> result = new ArrayList<T>(list.size());
        for (S s : list) {
            if (s == null) {
                continue;
            }
            result.add(convertTo(s));
        }

        return result;
    }

    /** 反向映射(List) */
    default List<S> convertFrom(List<T> list) {
        if (list == null) {
            return null;
        }

        List<S> result = new ArrayList<S>(list.size());
        for (T t : list) {
            if (t == null) {
                continue;
            }
            result.add(convertFrom(t));
        }

        return result;
    }

    /** 正向映射的后置处理,List映射会自动继承此配置 */
    @AfterMapping
    default void handleAfterConvertTo(S src, @MappingTarget T dest) {
        afterConvertTo(src, dest);
    }

    /** 反向映射的后置处理,List映射会自动继承此配置 */
    @AfterMapping
    default void handleAfterConvertFrom(T src, @MappingTarget S dest) {
        afterConvertFrom(src, dest);
    }

    /** 正向映射的后置处理,List映射会自动继承此配置 */
    default void afterConvertTo(S src, T dest) {
        //TODO 覆盖此方法处理其他复杂转换逻辑
    }

    /** 反向映射的后置处理,List映射会自动继承此配置 */
    default void afterConvertFrom(T src, S dest) {
        //TODO 覆盖此方法处理其他复杂转换逻辑
    }

//    /** 正向映射(stream) */
//    @InheritConfiguration(name = "convertTo")
//    Stream<T> convertTo(Stream<S> stream);
//
//    /** 反向映射(stream) */
//    @InheritConfiguration(name = "convertFrom")
//    Stream<S> convertFrom(Stream<T> stream);
}

@MapperConfig:定义一个映射器配置
@InheritConfiguration:正向映射自动继承转换类型相同属性名相同的字段
@InheritInverseConfiguration:反向映射自动继承转换类型相同属性名相同的字段
@AfterMapping:后置处理器,在自动转换后可以实现不同类型不同字段之间的自定义转换

实现具体的类型转换器

这里实现一个具体的DO—>DTO的类型转换器EditionMapping

/**
 * @author shihaowei
 * @date 2020/6/30 4:34 下午
 */
@Mapper(componentModel = "spring")
public interface EditionMapping extends BaseMapping<EditionDO, EditionDTO> {

    EditionMapping INSTANT = Mappers.getMapper(EditionMapping.class);

    @Override
    default void afterConvertTo(EditionDO src, EditionDTO dest) {
        dest.setOrderArray(src.getOrderarray());
        dest.setOrderList(src.getOrderlist());
    }
}

用于测试的两个实体类:
EditionDO

public class EditionDO {

    private Integer id;
    private String name;
    private Double memory;
    private String orderarray;
    private String orderlist;

    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 Double getMemory() {
        return memory;
    }

    public void setMemory(Double memory) {
        this.memory = memory;
    }

    public String getOrderarray() {
        return orderarray;
    }

    public void setOrderarray(String orderarray) {
        this.orderarray = orderarray;
    }

    public String getOrderlist() {
        return orderlist;
    }

    public void setOrderlist(String orderlist) {
        this.orderlist = orderlist;
    }

    @Override
    public String toString() {
        return "EditionDO{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", memory=" + memory +
                ", orderarray='" + orderarray + '\'' +
                ", orderlist='" + orderlist + '\'' +
                '}';
    }
}

EditionDTO

/**
 * @author shihaowei
 * @date 2020-06-10 16:35
 */
public class EditionDTO {

    private Integer id;
    private String name;
    private String memory;
    private String orderArray;
    private String orderList;

    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 getMemory() {
        return memory;
    }

    public void setMemory(String memory) {
        this.memory = memory;
    }

    public String getOrderArray() {
        return orderArray;
    }

    public void setOrderArray(String orderArray) {
        this.orderArray = orderArray;
    }

    public String getOrderList() {
        return orderList;
    }

    public void setOrderList(String orderList) {
        this.orderList = orderList;
    }

    @Override
    public String toString() {
        return "EditionDTO{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", memory=" + memory +
                ", orderArray='" + orderArray + '\'' +
                ", orderList='" + orderList + '\'' +
                '}';
    }
}

这里这两个类有两个字段名不同,需要在后置处理器里面去手动转换,只有类型相同属性名相同的属性才会自动转换,测试如下:
在这里插入图片描述
这里不同属性名转换成功。

如果相同属性名,但是类型不同的话,转换会出现什么问题呢?然后我把EditionDTO里面memory属性的类型改成Date,而源EditionDO里面memory属性的类型是Double,然后我们进行测试:

  @Test
    public void getEditionById2(){
        EditionDO editionDO = testService.getEditionById(1);
        System.err.println(editionDO);
        EditionDTO editionDTO = editionMapping.convertTo(editionDO);
        System.err.println(editionDTO);
    }

在这里插入图片描述
这里的解决方法就是自定义转换类型并切去接口继承
DoubleToDateMapping

/**
 * @author shihaowei
 * @date 2020/7/1 1:55 下午
 */
public interface DoubleToDateMapping {

    default Date DoubleToDate(Double memory){
        return new Date();
    }
}

然后在mapping转化器里面去继承这个接口,然后可以自动把Double类型转换成Date

@Mapper(componentModel = "spring")
public interface EditionMapping extends BaseMapping<EditionDO, EditionDTO>, DoubleToDateMapping {

    EditionMapping INSTANT = Mappers.getMapper(EditionMapping.class);

    @Override
    default void afterConvertTo(EditionDO src, EditionDTO dest) {
        dest.setOrderArray(src.getOrderarray());
        dest.setOrderList(src.getOrderlist());
    }
}

然后我们再次运行测试:
在这里插入图片描述
这里显示转换成功了,这里使用Double转Date的例子不太合情理,但是达到的目的就是不同类型的转换

注:针对相同属性字段不同类型的属性转换为String,正对常用的包装类型mapstruct封装李对这些常用类型的转换,不需要自己写转换

猜你喜欢

转载自blog.csdn.net/qq_39513430/article/details/107058700