2021-03-24 Java entity mapping tool MapStruct

Introduction: Make your DO (Business Entity Object), DTO (Data Transfer Object) data conversion simpler and more powerful

Preface

  In the software architecture, the layered structure is the most common. Each layer has its own independent and isolated business logic. Therefore, each layer has its own input and output objects, that is, you see various Os in the code, such as DO, DTO, VO, these data objects usually have many same or similar attribute objects. In the process of data transmission, from one O to another O, it usually needs to be assigned, from the initial get/set    

 

personDTO.setName(personDO.getName());
personDTO.setAge(personDO.getAge());
personDTO.setSex(personDO.getSex());
personDTO.setBirthday(personDO.getBirthday());

To the later BeanUtils (reduce the amount of code for set)

image.png

To the current MapStruct

 

1. MapStruct configuration

         The use of MapStuct is very simple, just import the corresponding jar package.

<properties>
    <lombok-mapstruct-binding.version>0.2.0</lombok-mapstruct-binding.version>
    <org.mapstruct.version>1.3.0.Final</org.mapstruct.version>
    <org.mapstruct.processor.version>1.3.0.Final</org.mapstruct.processor.version>
</properties>

<dependencies>
    <dependency>
        <groupId>org.mapstruct</groupId>
        <artifactId>mapstruct-jdk8</artifactId>
        <version>${org.mapstruct.version}</version>
    </dependency>
    <dependency>
        <groupId>org.mapstruct</groupId>
        <artifactId>mapstruct-processor</artifactId>
        <version>${org.mapstruct.processor.version}</version>
        <scope>provided</scope>
    </dependency>
</dependencies>

<configuration>
    <source>${java.version}</source>
    <target>${java.version}</target>
    <annotationProcessorPaths>
        <path>
            <groupId>org.mapstruct</groupId>
            <artifactId>mapstruct-processor</artifactId>
            <version>${org.mapstruct.processor.version}</version>
        </path>
        <path>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>${lombok.version}</version>
        </path>
        <path>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok-mapstruct-binding</artifactId>
            <version>${lombok-mapstruct-binding.version}</version>
        </path>
    </annotationProcessorPaths>
</configuration>

 

2. Principle

     MapStruct belongs to the generation of code that calls the get/set method for assignment during the compile period, and generates the corresponding java file. A little time is consumed during compilation in exchange for high performance at runtime.

 

3. How to use

First define an interface, according to the specification, we build a converter package under service or domainService

image

 

Obtain Mapper instance through dependency injection

@Mapper(componentModel = "spring")

image

 

 

 

3.1 For fields with the same name and attribute, there is no need to specify it in a special statement, and it will be automatically converted.

MapStructReq1

@Data
@Accessors(chain = true)
public class MapStructReq1 {

    private Integer id;
    private String name;
    @JsonFormat(pattern = "yyyy-MM-dd")
    private Date updateTime;

}

MapStructResp1:

@Data
@Accessors(chain = true)
public class MapStructResp1 {

    private Integer id;
    private String name;
    @JsonFormat(pattern = "yyyy-MM-dd")
    private Date updateTime;

}

 

converter:

image.png

 

 

serviceImpl:

image.png

 

 

controller:

image.png

After calling the demo1 interface, we can see that after assigning MapStructReq1, we successfully copied it to MapStructResp1. Return

image.png

 

3.2 For fields with different names and the same attribute, you can use Mapping annotations to specify.

MapStructReq1

@Data
@Accessors(chain = true)
public class MapStructReq1 {

    private Integer id;
    private String name;
    @JsonFormat(pattern = "yyyy-MM-dd")
    private Date updateTime;

}

MapStructResp2

@Data
public class MapStructResp2 {

    private Integer id;
    private String productName;
    @JsonFormat(pattern = "yyyy-MM-dd")
    private Date updateTime;

}

converter

@Mapping(source = "name", target = "productName")
MapStructResp2 req1ToResp2(MapStructReq1 req);

 

controller:

image.png

image.png

The name field in req1 is copied to productName in resp2

 

 

3.3 Support mapping multiple parameters into one type, just use @Mapping to specify.

converter:

    @Mapping(source = "req1.id", target = "id")
    @Mapping(source = "req2.productName", target = "name")
    @Mapping(source = "req1.updateTime", target = "updateTime")
    MapStructResp1 req1And2ToResp1(MapStructReq1 req1, MapStructReq2 req2);

controller:

image.png

image.png

Copy the id in req1 and the name in req2 to resp1

 

3.4 Automatic implicit conversion will be performed for basic data types

Such as int, long, String, Integer, Long, etc.

req3

@Data
@Accessors(chain = true)
public class MapStructReq3 {

    private String id;
    private int name;
    @JsonFormat(pattern = "yyyy-MM-dd")
    private Date updateTime;

}

resp1:

@Data
@Accessors(chain = true)
public class MapStructResp1 {

    private Integer id;
    private String name;
    @JsonFormat(pattern = "yyyy-MM-dd")
    private Date updateTime;

}

converter:

image.png

controller:

image.png

 

 

image.png

String type id is converted to int type, int type name is converted to String type

 

3.5 Copy of collection

req5

@Data
@Accessors(chain = true)
public class MapStructReq5 {

    private Integer id;
    private MapStructReq1 target;
    private List<MapStructReq1> list;

}

resp5

@Data
@Accessors(chain = true)
public class MapStructResp5 {

    private Integer id;
    private MapStructResp1 target;
    private List<MapStructResp1> list;

}

converter:

List<MapStructResp1> req1ListToResp1List(List<MapStructReq1> req1List);

controller:

image.png

image.png

 

3.6 Copy of nested objects

 

converter:

MapStructResp5 req5ToResp5(MapStructReq5 req);

 

controller:

image.png

Assign req1 to target and req1 with 4 different names to list

image.png

3.7 Mapping using java expressions

For complex mappings, java expressions are allowed to implement field mapping.

Pay attention to import the used classes.

 

req6

@Data
@Accessors(chain = true)
public class MapStructReq6 {

    private Integer id;
    private int price1;
    private int price2;

}

resp6

@Data
@Accessors(chain = true)
public class MapStructResp6 {

    private Integer id;
    private int price1;
    private int price2;

}

DemoUtils

public class DemoUtils {

    public static int add(int val1, int val2) {
        return val1 + val2;
    }
}

converter:

@Mapper(componentModel = "spring", imports = {DemoUtils.class})//Import classes used in java expressions, import multiple classes, separate 
public interface MapStructConverterDemo1 { 

    /** 
     * use java expressions in {} Mapping 
     * @param req 
     * @return 
     */ 
    @Mapping(target = "price1", expression = "java(req.getPrice1() + req.getPrice2())")// 
    Add directly @Mapping(target = " price2", expression = "java(DemoUtils.add(req.getPrice1(), req.getPrice2()))")//Use tool class to process 
    MapStructResp6 req6ToResp6(MapStructReq6 req); 
}

controller:

image.png

image.png

Reference link

https://www.cnblogs.com/gotten/p/13052911.html

Guess you like

Origin blog.csdn.net/weixin_43970890/article/details/115180592