Careeroza
MapStruct
Generated Mappers
MapStruct generates mapper code at compile time from an interface. No reflection at runtime, so it is as fast as hand-written code, and the compiler warns you about fields you forgot to map.
<properties>
<mapstruct.version>1.6.3</mapstruct.version>
</properties>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>${mapstruct.version}</version>
</dependency>
<!-- inside maven-compiler-plugin -->
<annotationProcessorPaths>
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${mapstruct.version}</version>
</path>
<!-- if you use Lombok, add lombok and lombok-mapstruct-binding here too -->
</annotationProcessorPaths>A MapStruct Mapper
import org.mapstruct.*;
@Mapper(componentModel = "spring") // generated class becomes a Spring bean
public interface ProductMapper {
@Mapping(target = "id", ignore = true)
@Mapping(target = "costPrice", ignore = true)
@Mapping(target = "createdOn", ignore = true)
Product toEntity(CreateProductRequest request);
@Mapping(target = "inStock", expression = "java(product.getStock() > 0)")
ProductResponse toResponse(Product product);
List<ProductResponse> toResponses(List<Product> products);
@Mapping(target = "id", ignore = true)
@Mapping(target = "costPrice", ignore = true)
@Mapping(target = "createdOn", ignore = true)
void update(UpdateProductRequest request, @MappingTarget Product target);
}
// Use it like any bean
@Service
public class ProductService {
private final ProductMapper mapper;
public ProductService(ProductMapper mapper) { this.mapper = mapper; }
}Example
After mvn compile MapStruct writes the implementation for you:
ls target/generated-sources/annotations/com/shopease/product/Example output
ProductMapperImpl.java
Manual or MapStruct?
| Manual mapper | MapStruct | |
|---|---|---|
| Setup | None | Dependency + annotation processor |
| Code to write | Every field by hand | Only the special cases |
| Forgotten field | Silent bug | Compile-time warning ("Unmapped target property") |
| Best for | Small apps, a few DTOs | Many entities and DTOs |
Tip: Add unmappedTargetPolicy = ReportingPolicy.ERROR to @Mapper to turn forgotten fields into build errors.