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.
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_NULLcopies nulls, but
RETURN_DEFAULTcan 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
idslist 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.
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.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.