Backend Development 7 min read

Master Advanced MapStruct Techniques for Efficient Java Bean Mapping

This article introduces MapStruct, a compile‑time Java bean mapping framework, and walks through its key features, expression mapping, qualifiedByName custom methods, null‑value strategies, and decorator usage, providing code examples for each advanced scenario.

macrozheng
macrozheng
macrozheng
Master Advanced MapStruct Techniques for Efficient Java Bean Mapping

Introduction

MapStruct is a Java compile‑time annotation‑processing framework that automatically maps one Java bean to another, generating code during compilation to achieve minimal runtime overhead.

Its main goals are to let developers perform property mapping with as little code as possible and with the lowest runtime cost.

Key Features

Concise – generates simple assignment statements.

High performance – no reflection.

Type‑safe – errors detected at compile time.

Flexible – custom conversion methods, type conversions, mapping strategies.

IDE support – code completion, error highlighting.

Expression Mapping

Use a Java expression to set a target field during mapping, e.g.:

<code>@Mapper(componentModel = "spring")
public interface MyMapper {
    @Mapping(target = "createTime", expression = "java(System.currentTimeMillis())")
    Target toTarget(Source source);
}
</code>

The generated implementation assigns

System.currentTimeMillis()

to

createTime

.

qualifiedByName

When default getter/setter mapping is insufficient, a custom method can be referenced with

qualifiedByName

:

<code>@Mapper(componentModel = "spring")
public interface MyMapper {
    @Mapping(target = "name", source = "name", qualifiedByName = "toUpperCase")
    Target toTarget(Source source);

    @Named("toUpperCase")
    default String toUpperCase(String value) {
        return value == null ? null : value.toUpperCase();
    }
}
</code>

The generated code calls

toUpperCase(source.getName())

.

nullValueMappingStrategy

Control how null source values are mapped. The default

RETURN_NULL

copies nulls, but

RETURN_DEFAULT

can create empty collections instead:

<code>@Mapper(componentModel = "spring",
        nullValueMappingStrategy = org.mapstruct.NullValueMappingStrategy.RETURN_DEFAULT)
public interface MyMapper {
    Target toTarget(Source source);
}
</code>

With this strategy, a null

ids

list in the source results in an empty list in the target.

Decorator

A decorator class can wrap the generated mapper to apply global post‑processing, such as setting default values for null fields:

<code>public abstract class YourMapperDecorator implements YourMapper {
    private final YourMapper delegate;
    public YourMapperDecorator(YourMapper delegate) { this.delegate = delegate; }

    @Override
    public Target toTarget(Source source) {
        Target result = delegate.toTarget(source);
        if (result != null && result.getField() == null) {
            result.setField("");
        }
        return result;
    }
}
</code>

Annotate the mapper interface with

@DecoratedWith(YourMapperDecorator.class)

to activate the decorator.

Javacode generationMapStructannotation-processingBean Mapping
macrozheng
Written by

macrozheng

Dedicated to Java tech sharing and dissecting top open-source projects. Topics include Spring Boot, Spring Cloud, Docker, Kubernetes and more. Author’s GitHub project “mall” has 50K+ stars.

0 followers
Reader feedback

How this landed with the community

login 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.