A brief introduction to MapStruct

MapStruct is an attribute mapping tool. You only need to define a Mapper interface, MapStruct will automatically implement the mapping interface, avoiding complex mapping implementation.

In a Java project, a variety of objects will be involved. Objects defined by Po, VO, DTO, Entity, DO and Domain are used in different scene modules. The mutual conversion between such objects requires a special tool to solve the conversion problem. The traditional approach was either to write your own converter or to use Apache or Spring’s BeanUtils to implement the conversion. Either way, there are obvious disadvantages. For example, the handwritten converter wastes time and requires method changes when new fields are added; BeanUtils, BeanCopier, etc. are all implemented using reflection, which is inefficient and only supports conversions with consistent attribute names.

MapSturct is an annotation processor that generates type-safe, high-performance, and dependency-free JavaBean mapping code. As a tool class, compared with handwriting, it is convenient and error-free.

The use of MapStruct

Introduction of depend on

The Maven project needs to introduce the following dependencies in poM files

<properties> <mapstruct.version> 1.3.0.final </ mapstruct.version> </properties> <dependencies> <dependency> <groupId>org.mapstruct</groupId> <artifactId>mapstruct-jdk8</artifactId> <version>${mapstruct.version}</version> </dependency> <dependency> <groupId>org.mapstruct</groupId> <artifactId>mapstruct-processor</artifactId> <version>${mapstruct.version}</version> </dependency> </dependencies>Copy the code

The basic use

Defining data Entities

@Data
@AllArgsConstructor
@TableName ( "user" )
public class User {
    @TableId ( value = "id", type = IdType.AUTO)
    private Long id;

    @TableField ( "user_name" )
    private String userName;

    @TableField ( "gender" )
    private Integer gender;

    @TableField ( "age" )
    private Integer age;

    @TableField ( "flag" )
    private Integer flag;
} 
Copy the code

Defining transformation entities

@Data
public class UserDto {
    private Long id;
    private String name;
    private String gender;
    private Integer age;
} 
Copy the code

Write the conversion interface

@Mapper public interface UserMapStruct { UserMapStruct INSTANCE = Mappers.getMapper(UserMapStruct.class); /** * Single object conversion * here simulate two cases: */ @mapping (source = "userName", */ @mapping (source = "userName", target = "name") @Mapping(target = "gender", Expression = "Java (com) rameo. Mapstruct. GenderEnum. Desc (user) getGender ()))") / / support expression UserDto userToDto (user user); */ List<UserDto> userToDtoList(List<User> userList); }Copy the code

Writing test methods

@RunWith(SpringRunner.class) @SpringBootTest public class UserMapStructTest { private User user; @Before public void before() { user = new User(1L, "sw", "shenzhen", 11, 1); } @Test public void test() { UserDto userDto = UserMapStruct.INSTANCE.userToDto(user); Assert.assertNotNull(userDto); Assert.assertEquals(userDto.getId(), 1); Assert.assertEquals(userDto.getName(), "sw"); Assert.assertEquals(userDto.getCity(), "shenzhen"); Assert.assertEquals(userDto.getAge(), 12); }}Copy the code

The examples above refer to the example on MapStruct’s official website. Lombok is used in the example. Please add related dependencies and plug-ins to use the lombok plug-in.

MapStruct principle description

  1. intarget/generated-sources/annotationsYou can see in the code that it generates oneThe implementation classAnd the code is similar to what we write by hand. This code, generated at compile time, performs much faster than reflection.

  1. MapStruct is a class file that dynamically generates set/ GET code at compile time and calls the class file directly at run time. There is actually still set/ GET code, but you don’t have to write it by hand.

MapStruct Conversion mode

  1. Attribute name same, direct conversion, similar to BeanUtils conversion defense
  2. Example @mapping (source = “userName”, target = “name”)

Note the use of MapStruct

  • If one of multiple objects is NULL, null is returned
  • As with one-to-one conversions, attributes are automatically matched by name. Therefore, those with the same name and type need no special treatment
  • If multiple original objects have attributes with the same name, you need to use the @mapping annotation to specify attributes to avoid ambiguity
  • When multiple properties are inconsistent, there are two solutions

  1. Add multiple @Mapping (recommended)
  2. / / “+ @mappings” + @mappings + @mappings + @mappings + @mappings + @mappings + @mappings + @mappings

The resources

  • Liverpoolfc.tv: mapstruct.org/
  • Github address: github.com/mapstruct/m…
  • Example sharing: github.com/mapstruct/m…