Last updated: December 10, 2021

Using MapStruct with Maven and Lombok

MapStruct is a Java library to simplify data transfer between classes and avoid writing boilerplate code. The following article will show the steps to automate the mapping between a JPA entity and a DTO in a Spring Boot application.

Backgrounds

For our example, we use the following technologies:

As developers, all we need to do is provide an interface that defines the desired mapping methods. MapStruct then generates the implementing class at build time - so our initial setup is a bit more extensive.

Maven Setup

In our pom.xml, we first need to add the dependency that will later allow us to define our mapper.

Furthermore, we need to extend the maven-compiler-plugin to activate the code generation of MapStruct.

Lombok is our first annotation processor, followed directly by MapStruct. Another reference to lombok-mapstruct-binding is necessary for these two libraries to work together. Without Lombok, only the mapstruct-processor would be needed at this point.

Mapper Interface

Now let's get to the core of our example - the mapper. In our example, there is a "CarPart" entity that has a primary key, two data fields as well as a reference to a "Supplier".

Our JPA Entity example

Our DTO contains all fields of the entity with further annotations for validation when used in a RestController. The reference to the Supplier is specified in form of the foreign key id.

Our example DTO

With these classes in place, we can now define the first version of our mapper. The "CarPartMapper" contains two methods for mapping in both directions. By annotating the interface with @Mapper, MapStruct will parse it and provide an implementing class. With componentModel = "spring" the class is added to Spring's application context and can be referenced later on in our service using @Autowired.

First version of our Mapper

The provided methods are automatically parsed by MapStruct. One parameter is the source object and the parameter with @MappingTarget defines the target object. Without a @MappingTarget the target object would be newly initialized; this however isn' t desired in our case. The class generated by MapStruct will automatically map all fields with the same name - in our case id, typeCode and releaseDate.

With the @Mapping annotation we can add special handlings for single fields. Since the id field is automatically generated by our persistence layer (GenerationType.IDENTITY), it should not be taken from the DTO to the entity. For the reference to the Supplier we want to add a custom handling, so this field should be ignored as well.

Mapping the foreign key

Lastly, we want to handle the reference to the Supplier by adding the following two default methods to our interface:

Adding custom behaviour with @AfterMapping

By annotating them with @AfterMapping we tell MapStruct to call the method after the initial mapping. With @Context we can add additional parameters to the method - we use this ability here to provide the SupplierRepository. If the specified Supplier does not exist, a 404 error should be returned.

With this, our mapper is ready and can be used in our service.

Using our new Mapper for creating a CarPart

Bootify provides a free tool to create a Spring Boot application with a custom database schema and REST API. The Professional Plan also provides an option for MapStruct, so the required mappers are automatically generated and added to your code base.

Learn more
or see pricing