Backend Development 6 min read

Advanced MapStruct Usage: expression, qualifiedByName, nullValueMappingStrategy, and Decorator

This article introduces MapStruct, a compile‑time Java bean‑mapping framework, and demonstrates advanced features such as expression‑based mappings, qualifiedByName for custom conversions, nullValueMappingStrategy for handling nulls, and the use of Decorator classes to apply global post‑processing logic.

Code Ape Tech Column
Code Ape Tech Column
Code Ape Tech Column
Advanced MapStruct Usage: expression, qualifiedByName, nullValueMappingStrategy, and Decorator

MapStruct is a Java compile‑time annotation‑processing framework that automatically generates code to map one Java bean to another, aiming for minimal code and optimal runtime performance by avoiding reflection.

Key characteristics of MapStruct include concise generated code, excellent performance, type safety, flexibility through custom conversion methods, and strong IDE support.

Expression Mapping

You can execute a Java expression during mapping. For example, the following mapper sets the createTime field of the target object to the current system time:

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

The generated implementation assigns System.currentTimeMillis() to target.setCreateTime .

qualifiedByName

By default, MapStruct copies values using standard getters and setters. When a custom transformation is required—such as converting a string to uppercase—you can use qualifiedByName together with a named method.

@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()) before setting the target field.

nullValueMappingStrategy

The default strategy NullValueMappingStrategy.RETURN_NULL maps a null source to a null target field. To return a default value—such as an empty list—use NullValueMappingStrategy.RETURN_DEFAULT either at the method or class level.

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

With this strategy, when source.ids is null, the generated mapper creates an empty ArrayList for target.ids instead of leaving it null.

Decorator

A Decorator class can wrap the generated mapper to apply global post‑processing, such as providing 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) so that calls to toTarget are intercepted by the decorator.

Javacode generationbackend developmentMapStructdecoratorBean Mapping
Code Ape Tech Column
Written by

Code Ape Tech Column

Former Ant Group P8 engineer, pure technologist, sharing full‑stack Java, job interview and career advice through a column. Site: java-family.cn

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.