SoFunction
Updated on 2025-04-05

Tutorial on using MapStruct

Use of MapStruct

MapStruct is a code generator that uses an annotation processor to implement mapping between Java beans.

MapStruct reduces the effort to manually write mapped code by automatically generating mapped code at compile time and helps keep code consistency and accuracy.

Here are the basic usage methods of MapStruct:

1. Add dependencies

First, you need to add MapStruct dependencies to the build configuration of your project. For Maven and Gradle, add the following dependencies:

  • Maven:
<dependencies>
    <dependency>
        <groupId></groupId>
        <artifactId>mapstruct</artifactId>
        <version>1.4.</version>
    </dependency>
</dependencies>

<build>
    <plugins>
        <plugin>
            <groupId></groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.8.1</version>
            <configuration>
                <source>1.8</source>
                <target>1.8</target>
                <annotationProcessorPaths>
                    <path>
                        <groupId></groupId>
                        <artifactId>mapstruct-processor</artifactId>
                        <version>1.4.</version>
                    </path>
                </annotationProcessorPaths>
            </configuration>
        </plugin>
    </plugins>
</build>
  • Gradle:
dependencies {
    implementation ':mapstruct:1.4.'
    annotationProcessor ':mapstruct-processor:1.4.'
}

2. Define the mapping interface

Create an interface and use@MapperAnnotation, this interface will define the mapping rules between the source object and the target object.

import ;
import ;

@Mapper
public interface MyMapper {
    MyMapper INSTANCE = ();

    // Define the mapping method from the source object to the target object    TargetObject map(SourceObject source);
}

3. Use the mapping method

In business logic, you can use defined mapping interfaces to transform objects.

public class MyService {
    public TargetObject convert(SourceObject source) {
        return (source);
    }
}

4. Define custom mapping methods

If you need custom mapping logic, you can define a@MappingAnnotated method and specify mapping rules in it.

@Mapper
public interface MyMapper {
    @Mapping(target = "targetProperty", source = "sourceProperty")
    @Mapping(target = "targetProperty2", expression = "java((source.getSourceProperty2()))")
    TargetObject map(SourceObject source);
}

5. Handle complex mappings

In this example,@MappingAnnotations are used to specify the attribute mapping relationship between the source object and the target object.sourceAttribute specifies the attribute name of the source object.targetAttribute specifies the attribute name of the target object.

@Mapper
public interface MyMapper {
    @Mapping(target = "dateOfBirth", source = "birthYear", qualifiedByName = "yearToCalendar")
    TargetObject map(SourceObject source);

    @Named("yearToCalendar")
    default Date yearToCalendar(int year) {
        Calendar calendar = ();
        (year, , 1);
        return ();
    }
}

For more complex mapping scenarios, such as the need to convert data types or call methods, MapStruct also provides corresponding annotations to support it.

  1. Custom Mapping: Can be used@MappingAnnotatedexpressionorqualifiedByNameAttributes customize mapping logic.
  2. Collection Mapping: Can be used@IterableMappingand@MapMappingAnnotation to handle mapping of collection types.
  3. Enumeration Mapping: Enumeration types can be mapped directly, or through@MappingAnnotatedenumNamedProperties to specify the mapping rules for enumerations.
  4. Use constructor mapping: If the target class has a constructor, you can use it@MappingAnnotatedconstructorProperties to specify the use of constructors for mapping.
  5. Nested property mapping: Can map nested object properties.
  6. Reverse mapping: You can define a reverse mapping method and use@MappingAnnotatedinverseProperties to refer to forward mapping methods.
  7. Enhance Mapper with Decorators: Can be used@DecoratedWithAnnotations are used to decorate the Mapper interface to implement more complex mapping logic.
  8. Mapping inheritance: Mapping configuration can be shared by inheritance.
  9. Preprocessing and post-processing using @BeforeMapping and @AfterMapping: Custom logic can be executed before and after the mapping method is executed.
  10. Passing context parameters using @Context: Additional context parameters can be passed in the mapping method.

6. Integrate Spring

MapStruct can also be integrated with the Spring framework, allowing Spring-managed beans to be injected into the mapper.

This needs to be used on the Mapper interface@Mapper(componentModel = "spring")Annotation to specify Spring as the component model. Then, you can use@AutowiredAnnotation to inject Spring-managed beans.

@Mapper(componentModel = "spring")
public interface MyMapper {
    TargetObject map(SourceObject source);
}

This way, the MapStruct mapper can be automatically assembled as a Spring Bean.

By using MapStruct, you can reduce boilerplate code written manually, improve development efficiency, and reduce errors caused by manual mapping.

Summarize

The above is personal experience. I hope you can give you a reference and I hope you can support me more.