Master Java Entity Mapping with MapStruct: A Complete Guide

This article introduces the open‑source MapStruct library for Java, shows how to configure Maven, defines entity and DTO classes, demonstrates basic and advanced mapping techniques—including list conversion, multi‑object merging, and default values—while providing complete code examples and explanations.

Java High-Performance Architecture
Java High-Performance Architecture
Java High-Performance Architecture
Master Java Entity Mapping with MapStruct: A Complete Guide

Many developers struggle with writing boilerplate code for converting entities, especially when the entities have many fields. This article introduces the open‑source project MapStruct , which enables elegant and concise entity mapping, simplifying the code.

Official site: https://mapstruct.org/

Below is the Maven configuration needed to use MapStruct:

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
    <org.mapstruct.version>1.4.1.Final</org.mapstruct.version>
    <org.projectlombok.version>1.18.12</org.projectlombok.version>
</properties>

<dependencies>
    <dependency>
        <groupId>org.mapstruct</groupId>
        <artifactId>mapstruct</artifactId>
        <version>${org.mapstruct.version}</version>
    </dependency>
    <!-- lombok dependencies should not end up on classpath -->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>${org.projectlombok.version}</version>
        <scope>provided</scope>
    </dependency>
    <!-- for older IDEA versions, add the processor dependency -->
    <dependency>
        <groupId>org.mapstruct</groupId>
        <artifactId>mapstruct-processor</artifactId>
        <version>${org.mapstruct.version}</version>
        <scope>provided</scope>
    </dependency>
</dependencies>

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.8.1</version>
            <configuration>
                <source>1.8</source>
                <target>1.8</target>
                <annotationProcessorPaths>
                    <path>
                        <groupId>org.projectlombok</groupId>
                        <artifactId>lombok</artifactId>
                        <version>${org.projectlombok.version}</version>
                    </path>
                    <path>
                        <groupId>org.mapstruct</groupId>
                        <artifactId>mapstruct-processor</artifactId>
                        <version>${org.mapstruct.version}</version>
                    </path>
                </annotationProcessorPaths>
            </configuration>
        </plugin>
    </plugins>
</build>

Version compatibility notes: Maven compiler plugin should be 3.6.0 or newer, Lombok 1.16.16 or newer, and the Lombok‑MapStruct annotation processor must be added; otherwise you may encounter errors such as "No property named \"aaa\" exists in source parameter(s)." which are caused by missing getters/setters generated by Lombok.

Below are the core entity, DTO, and mapper definitions:

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class Student {
    private String name;
    private int age;
    private GenderEnum gender;
    private Double height;
    private Date birthday;
}

public enum GenderEnum {
    Male("1", "男"),
    Female("0", "女");
    private String code;
    private String name;
    public String getCode() { return this.code; }
    public String getName() { return this.name; }
    GenderEnum(String code, String name) { this.code = code; this.name = name; }
}

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class StudentVO {
    private String name;
    private int age;
    private String gender;
    private Double height;
    private String birthday;
}

@Mapper
public interface StudentMapper {
    StudentMapper INSTANCE = Mappers.getMapper(StudentMapper.class);

    @Mapping(source = "gender.name", target = "gender")
    @Mapping(source = "birthday", target = "birthday", dateFormat = "yyyy-MM-dd HH:mm:ss")
    StudentVO student2StudentVO(Student student);
}

The mapper interface is the only part you need to write manually; the implementation is generated at compile time.

Mapper generation diagram
Mapper generation diagram

Using the generated mapper is straightforward:

public class Test {
    public static void main(String[] args) {
        Student student = Student.builder()
            .name("小明")
            .age(6)
            .gender(GenderEnum.Male)
            .height(121.1)
            .birthday(new Date())
            .build();
        System.out.println(student);
        // Actual conversion code
        StudentVO studentVO = StudentMapper.INSTANCE.student2StudentVO(student);
        System.out.println(studentVO);
    }
}
Conversion result
Conversion result

MapStruct can map fields, change field types, and apply custom formatting, such as date conversion.

You can also define custom methods for formatting, for example:

@Mapper
public interface StudentMapper {
    StudentMapper INSTANCE = Mappers.getMapper(StudentMapper.class);

    @Mapping(source = "gender", target = "gender")
    @Mapping(source = "birthday", target = "birthday", dateFormat = "yyyy-MM-dd HH:mm:ss")
    StudentVO student2StudentVO(Student student);

    default String getGenderName(GenderEnum gender) {
        return gender.getName();
    }
}

1. List Conversion

Mapping a list of entities follows the same configuration:

@Mapper
public interface StudentMapper {
    StudentMapper INSTANCE = Mappers.getMapper(StudentMapper.class);

    @Mapping(source = "gender.name", target = "gender")
    @Mapping(source = "birthday", target = "birthday", dateFormat = "yyyy-MM-dd HH:mm:ss")
    StudentVO student2StudentVO(Student student);

    List<StudentVO> students2StudentVOs(List<Student> studentList);
}

public static void main(String[] args) {
    Student student = Student.builder()
        .name("小明")
        .age(6)
        .gender(GenderEnum.Male)
        .height(121.1)
        .birthday(new Date())
        .build();
    List<Student> list = new ArrayList<>();
    list.add(student);
    List<StudentVO> result = StudentMapper.INSTANCE.students2StudentVOs(list);
    System.out.println(result);
}
List conversion example
List conversion example

2. Mapping Multiple Source Objects to One Target

@Mapper
public interface StudentMapper {
    StudentMapper INSTANCE = Mappers.getMapper(StudentMapper.class);

    @Mapping(source = "student.gender.name", target = "gender")
    @Mapping(source = "student.birthday", target = "birthday", dateFormat = "yyyy-MM-dd HH:mm:ss")
    @Mapping(source = "course.courseName", target = "course")
    StudentVO studentAndCourse2StudentVO(Student student, Course course);
}

public static void main(String[] args) {
    Student student = Student.builder()
        .name("小明")
        .age(6)
        .gender(GenderEnum.Male)
        .height(121.1)
        .birthday(new Date())
        .build();
    Course course = Course.builder()
        .id(1L)
        .courseName("语文")
        .build();
    StudentVO studentVO = StudentMapper.INSTANCE.studentAndCourse2StudentVO(student, course);
    System.out.println(studentVO);
}
Multiple source mapping
Multiple source mapping

3. Default Values

@Mapper
public interface StudentMapper {
    StudentMapper INSTANCE = Mappers.getMapper(StudentMapper.class);

    @Mapping(source = "student.gender.name", target = "gender")
    @Mapping(source = "student.birthday", target = "birthday", dateFormat = "yyyy-MM-dd HH:mm:ss")
    @Mapping(source = "course.courseName", target = "course")
    @Mapping(target = "name", source = "student.name", defaultValue = "张三")
    StudentVO studentAndCourse2StudentVO(Student student, Course course);
}
Default value mapping
Default value mapping
Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavamavenmapstructmapperEntity Mapping
Java High-Performance Architecture
Written by

Java High-Performance Architecture

Sharing Java development articles and resources, including SSM architecture and the Spring ecosystem (Spring Boot, Spring Cloud, MyBatis, Dubbo, Docker), Zookeeper, Redis, architecture design, microservices, message queues, Git, etc.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.