Mastering MapStruct: Fast, Type‑Safe Java Bean Mapping with Real‑World Examples

This article introduces MapStruct, a compile‑time Java bean‑mapping code generator, explains its core concepts, shows step‑by‑step examples—including Maven dependencies, entity and DTO definitions, mapper interfaces, custom conversions, and advanced configurations—while comparing its performance to other copy utilities and highlighting deep‑copy behavior.

Su San Talks Tech
Su San Talks Tech
Su San Talks Tech
Mastering MapStruct: Fast, Type‑Safe Java Bean Mapping with Real‑World Examples

Official Introduction

MapStruct is a code generator that simplifies JavaBean mapping by generating plain‑method calls at compile time, offering fast, type‑safe, and easy‑to‑understand mapping implementations.

Why Use MapStruct

Multi‑layer applications often need to map between different object models (e.g., entities and DTOs). Writing such mapping code manually is tedious and error‑prone; MapStruct automates this process, providing high performance and thorough error checking.

How It Works

MapStruct is a Java annotation processor that can be used with Maven, Gradle, or IDEs. It uses sensible defaults but allows custom behavior through configuration.

Simple Implementation

1. Add Maven dependencies

<dependency>
	<groupId>org.mapstruct</groupId>
	<artifactId>mapstruct-jdk8</artifactId>
	<version>1.3.0.Final</version>
</dependency>
// annotation processor
<dependency>
	<groupId>org.mapstruct</groupId>
	<artifactId>mapstruct-processor</artifactId>
	<version>1.2.0.Final</version>
</dependency>

2. Define entity and DTO classes

@NoArgsConstructor
@AllArgsConstructor
@Data
public class Car {
    private String make;
    private int numberOfSeats;
    private CarType type;
}

@Data
@NoArgsConstructor
@AllArgsConstructor
public class CarDto {
    private String make;
    private int seatCount;
    private String type;
}

3. Create mapper interface

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

    @Mapping(source = "numberOfSeats", target = "seatCount")
    CarDto carToCarDto(Car car);
}

Analysis @Mapper marks the interface for MapStruct processing.

The mapping method converts a Car to CarDto; the method name is arbitrary. @Mapping handles properties with different names or types.

MapStruct generates an implementation class that can be obtained via Mappers.getMapper.

4. Generated implementation

The compiled target folder contains CarMapperImpl.class, which includes generated getters/setters and special handling for enums.

5. Client test

@Test
public void shouldMapCarToDto() {
    Car car = new Car("Morris", 5, CarType.SEDAN);
    CarDto carDto = CarMapper.INSTANCE.carToCarDto(car);
    System.out.println(carDto);
}

Mapper Configuration

The @Mapper annotation supports a componentModel attribute with four options:

default : obtain mapper via Mappers.getMapper.

cdi : generates an application‑scoped CDI bean, injectable with @Inject.

spring : generates a Spring bean, injectable with @Autowired.

jsr330 : generates a bean annotated with @Named and @Singleton, injectable with @Inject.

Custom implementations can also be injected using @Autowired.

Advanced Features

Using uses for custom conversions

@Mapper(uses = {BooleanStrFormat.class})
public interface CarMapper { ... }

@Component
public class BooleanStrFormat {
    public String toStr(boolean type) { return type ? "Y" : "N"; }
    public boolean toBoolean(String type) { return "Y".equals(type); }
}

Mapping method example:

@Mapping(target = "type", expression = "java(new com.ittest.controller.BooleanStrFormat().toStr(carVo.isType()))")
CarDto carVoToDtoWithExpression(CarVo carVo);

Multiple source objects to one target

Benz4SMall mallCarToBenzMall(Car car, Mall4S mall4S);

Generated implementation merges fields from both sources.

Updating existing objects

void updateBwmCar(Car car, @MappingTarget BMWCar bwmCar);

MapStruct generates code that copies non‑null source fields into the target instance.

Deep vs. Shallow Copy

MapStruct creates new objects, performing a deep copy rather than a shallow reference copy.

Performance Comparison

Benchmarks show MapStruct outperforms manual copy, cglib, Spring BeanUtils, Apache BeanUtils, and others, achieving roughly 10× the speed of Apache BeanUtils and 4‑5× that of Spring BeanUtils for large data volumes.

Conclusion: For high‑performance bean mapping, especially with large datasets, MapStruct (or BeanCopier) provides the best speed and type safety.
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.

JavaCode Generationspringmavenmapstructbean-mapping
Su San Talks Tech
Written by

Su San Talks Tech

Su San, former staff at several leading tech companies, is a top creator on Juejin and a premium creator on CSDN, and runs the free coding practice site www.susan.net.cn.

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.