Spring Framework

[MapStruct] List에서 요소 하나를 매핑할 함수 지정하는 법 - @IterableMapping

개발자 이우진 2024. 8. 24. 16:30

개요

    @IterableMapping(qualifiedByName = "toDto(RunHabit)")
    List<RunHabitDto> toDtoList(List<RunHabit> runHabits);

@IterableMapping을 이용하면 리스트를 매핑할 때 요소 하나를 매핑할 메소드를 지정할 수 있다. 객체 하나를 매핑할 때 사용한 메소드를 재사용하여 같은 규칙을 사용할 수 있는 장점이 있다.

 

설명

@Mapper(componentModel = "spring", uses = {HabitAlertMapper.class})
@Named("RunHabitMapper")
public interface RunHabitMapper {
    RunHabitMapper INSTANCE = Mappers.getMapper(RunHabitMapper.class);

    @Named("toDto(RunHabit)")
    @Mapping(source = "user.id", target = "userId")
    @Mapping(target = "habitAlerts", ignore = true)
    @Mapping(target = "historyCountByStatus", ignore = true)
    RunHabitDto toDto(RunHabit runHabit);

    @IterableMapping(qualifiedByName = "toDto(RunHabit)")
    List<RunHabitDto> toDtoList(List<RunHabit> runHabits);

@IterableMapping을 설정하지 않았을 때 생성된 MapperImpl의 코드를 보면 내가 정의한 toDto(RunHabit) 메소드를 쓸 것이라는 기대와 달리 필드 하나를 일일이 set하는 함수가 생성되었다. 그 결과 userId라는 필드는 매핑이 되지 않아 null로 리턴되는 현상이 나타났다.

이처럼 리스트에서 각 요소를 매핑할 메소드를 지정하는 데 쓸 수 있는 것이 @IterableMapping이다. @IterableMapping의 qualifiedByName 설정으로 메소드의 별명을 지정해 주면 MapperImpl에서 원하는 대로 이미 정의한 toDto() 메소드를 재활용하는 것을 확인할 수 있다.

    @Override
    public List<RunHabitDto> toDtoList(List<RunHabit> runHabits) {
        if ( runHabits == null ) {
            return null;
        }

        List<RunHabitDto> list = new ArrayList<RunHabitDto>( runHabits.size() );
        for ( RunHabit runHabit : runHabits ) {
            list.add( toDto( runHabit ) );
        }

        return list;
    }

 

출처

https://stackoverflow.com/questions/52162518/mapstruct-list-mapping-is-not-using-single-mapping-when-annotated-by-named

 

MapStruct: List mapping is not using single mapping when annotated by @Named

I have the following Mapper @Mapper @Named("RoleBaseMapper") public interface RoleBaseMapper { @Mapping(target = "code", source = "name") @Named("mapToBase") RoleGuiBaseDto mapToBase...

stackoverflow.com