Your First Mapper: From @Mapper to Perfect DTOs


Creating a Basic Mapper Interface

MapStruct makes it easy to create mappers for transforming between entity and DTO classes. To start, define an interface and annotate it with @Mapper. MapStruct will generate the implementation automatically at build time.


@Mapper(componentModel = "spring")
public interface UserMapper {
    UserDto toDto(User user);
    User toEntity(UserDto userDto);
}

The componentModel = "spring" option registers the mapper as a Spring bean, allowing it to be injected wherever needed.

Understanding @Mapping Annotations

The @Mapping annotation is used when source and target fields do not match by name or need transformation. It's placed above the method to guide MapStruct during generation.


@Mapping(source = "firstName", target = "name")
UserDto toDto(User user);

You can chain multiple @Mapping annotations for complex mappings:


@Mapping(source = "email", target = "contactEmail")
@Mapping(source = "phone", target = "contactPhone")
UserDto toDto(User user);

Field Name Conventions and Automatic Mapping

MapStruct supports automatic mapping when the source and target fields share the same name and type. This makes most simple mappings zero-config.

For example, if both User and UserDto have a username field of type String, MapStruct will map it automatically without the need for a @Mapping annotation.

To benefit fully from this, follow consistent naming conventions across your DTOs and entities.

Testing Your Generated Mapper

Once MapStruct generates the implementation, you can write unit tests to ensure it works as expected. Here’s a simple JUnit test:


@SpringBootTest
class UserMapperTest {

    @Autowired
    private UserMapper userMapper;

    @Test
    void shouldMapUserToDto() {
        User user = new User();
        user.setUsername("john");
        user.setEmail("john@example.com");

        UserDto dto = userMapper.toDto(user);

        assertEquals("john", dto.getUsername());
        assertEquals("john@example.com", dto.getEmail());
    }
}

Testing your mapper early ensures correctness and helps catch changes that break mapping logic.

Conclusion

Getting started with MapStruct is straightforward. By defining a mapper interface, using @Mapping annotations when needed, and following naming conventions, you can generate clean, efficient DTO transformations. Adding unit tests gives you confidence as your project grows.

Post a Comment

0 Comments