-
[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()); }
'자바 > mapstruct' 카테고리의 다른 글
[MapStruct] Enum과 Integer 간에 매핑 설정 방법 (0) 2021.01.16 [MapStruct] 기본 매핑 (0) 2020.11.26 [MapStruct] 여러 개의 소스 파라미터를 가지는 매핑 함수 (0) 2020.11.23