ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [MapStruct] 중첩된 빈 프로퍼티를 현재 타겟에 매핑시키기
    자바/mapstruct 2020. 12. 1. 14:34

    중첩된 소스 객체의 모든 프로퍼티들에 대해서 명시적으로 선언하기를 원하지 않으면, target 파라미터에 "."를 사용할 수 있습니다.

    "."는 MapStruct로 하여금 소스 객체의 모든 프로퍼티들에 대해서 타겟 객체에 매핑될 수 있게 지원합니다.

    해당 기능은 MapStruct 1.4.1에서부터 지원됩니다.
    @Getter
    @NoArgsConstructor
    @JsonInclude(JsonInclude.Include.NON_EMPTY)
    public class CustomerDto {
        private Long id;
        private Record record;
        private Account account;
    
        @Builder
        public CustomerDto(Long id, Record record, Account account) {
            this.id = id;
            this.record = record;
            this.account = account;
        }
    }
    @Getter
    @NoArgsConstructor
    @JsonInclude(JsonInclude.Include.NON_EMPTY)
    public class Account {
        String name;
        int age;
        String phone;
        String address;
        String email;
    
        @Builder
        public Account(String name, int age, String phone, String address, String email) {
            this.name = name;
            this.age = age;
            this.phone = phone;
            this.address = address;
            this.email = email;
        }
    }
    @Getter
    @NoArgsConstructor
    @JsonInclude(JsonInclude.Include.NON_EMPTY)
    public class Record {
        String name;
        Long number;
    
        @Builder
        public Record(String name, Long number) {
            this.name = name;
            this.number = number;
        }
    }
    @Getter
    @NoArgsConstructor
    @JsonInclude(JsonInclude.Include.NON_EMPTY)
    public class Customer {
        Long id;
        String name;
        Long number;
        int age;
        String phone;
        String address;
        String email;
    
        @Builder
        public Customer(Long id, String name, Long number, int age, String phone, String address, String email) {
            this.id = id;
            this.name = name;
            this.number = number;
            this.age = age;
            this.phone = phone;
            this.address = address;
            this.email = email;
        }
    }
    @Mapper
    public interface CustomerMapper {
        CustomerMapper INSTANCE = Mappers.getMapper(CustomerMapper.class);
    
        @Mapping( target = "name", source = "record.name" )
        @Mapping( target = ".", source = "record" )
        @Mapping( target = ".", source = "account" )
        Customer customerDtoToCustomer(CustomerDto customerDto);
    }

    MapStruct에 의해서 생성된 코드는 CustomerDto.record의 모든 프로퍼티에 대해서 Customer객체로 직접적으로 매핑하게 됩니다.

    Customer.account에 대해서도 동일하게 동작합니다.

     

    만약 충돌이 발생한다면 명시적으로 매핑을 정의함으로써 해결할 수 있습니다.

    위의 예시에서 name 프로퍼티는 CustomerDto.record와 CustomerDto.account에서 동시에 존재하는 프로퍼티입니다.

    @Mapping( target = "name", source = "record.name" ) 의 경우 CustomerDto.record의 name 필드를 Customer의 name 필드에 매핑하도록 명시적으로 선언하여 충돌을 해결하였습니다.

     

    "."는 "target this" 표기법으로 구조적(Hierarchical)인 객체를 평평한(Flat) 객체로 매핑 시킬 때나 그 반대의 경우(@InheritInverseConfiguration)에도 매우 유용합니다.

     

    @Test
    public void MapStruct테스트() throws Exception {
        Account account = Account.builder()
                .name("우쭈뿌라1")
                .age(39)
                .phone("01000000000")
                .email("uchupura@gmail.com")
                .address("경기도 하남시")
                .build();
        Record record = Record.builder()
                .name("우쭈뿌라2")
                .number(12345L)
                .build();
        CustomerDTO customerDTO = CustomerDTO.builder()
                .id(1L)
                .account(account)
                .record(record)
                .build();
    
        Customer customer = CustomerMapper.INSTANCE.customerDtoToCustomer(customerDTO);
    
        assertThat(customer.getName()).isEqualTo(record.getName());
        assertThat(customer.getPhone()).isEqualTo(account.getPhone());
        assertThat(customer.getNumber()).isEqualTo(record.getNumber());
    }

    댓글

Designed by Tistory.