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

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

The generated implementation assigns System.currentTimeMillis() to createTime.

qualifiedByName

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

@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();
    }
}

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:

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

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:

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;
    }
}

Annotate the mapper interface with @DecoratedWith(YourMapperDecorator.class) to activate the decorator.

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.

mapstructAnnotation Processingbean-mappingcode-generation
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

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.