Mapstruct Tutorial - Java에서 매퍼 코드 자동 생성

일반 매핑

public class Mapper {

    public Employee toEmployee(EmployeeDTO dto) {

        Employee employee=new Employee();

        employee.setName(dto.getName());
        employee.setJobTitle(dto.getJobTitle());
        employee.setJoinedDate(dto.getJoinedDate());
        employee.setMobileNo(dto.getMobileNo());
        employee.setDepartment(dto.getDepartment());
        employee.setSalary(dto.getSalary());

        return employee;

    }
}


맵스트럭이 뭔가요?

MapStruct는 Java 모델과 DTO 간의 매핑 구현을 크게 단순화하는 코드 생성기입니다. Mapstruck을 사용하면 매퍼 코드를 길게 할 필요 없이 단순히 소스 및 대상 클래스를 말해야 합니다.

MapStruck은 소스에서 대상 클래스로 이름을 기반으로 필드를 매핑하는 매퍼 코드를 자동으로 생성하며 필드에 대한 사용자 지정 매핑을 전달할 수 있습니다.

mapstruck maven 의존성

<org.mapstruct.version>1.5.2.Final</org.mapstruct.version>

<dependency>
    <groupId>org.mapstruct</groupId>
    <artifactId>mapstruct</artifactId>
    <version>${org.mapstruct.version}</version>
</dependency>


엔티티 또는 DTO 클래스에서 상용구 코드를 줄이기 위해 Lombok을 사용하는 경우 pom.xml에 아래를 추가하십시오.

mapstruck에서 매퍼를 만드는 방법은 무엇입니까?

<build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <annotationProcessorPaths>
                        <path>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                            <version>${org.projectlombok.version}</version>
                        </path>
                        <path>
                            <groupId>org.mapstruct</groupId>
                            <artifactId>mapstruct-processor</artifactId>
                            <version>${org.mapstruct.version}</version>
                        </path>
                    </annotationProcessorPaths>
                </configuration>
            </plugin>
        </plugins>
    </build>


인터페이스를 만들고 @Mapper로 주석을 답니다. 이제 메서드를 정의해 보겠습니다. 메소드 매개변수는 소스 역할을 하고 메소드 리턴 유형은 대상 역할을 합니다. MapStruck은 필드 이름이 동일한 경우 소스 필드를 대상 필드에 매핑합니다.

이름이 같은 필드 매핑

기본적으로 MapStruck은 소스와 대상에 동일한 이름의 필드가 있는 경우 이름별로 필드를 매핑한 다음 매퍼가 필드를 매핑합니다. EmployeeDTO와 Employee 클래스는 모두 동일한 속성 이름을 가집니다.

@Mapper(componentModel = "spring")
public interface EmployeeMapper {

    Employee toEmployee(EmployeeDTO employeeDTO);

}


componentModel = "spring"은 이 매퍼를 애플리케이션에서 autowire할 수 있는 spring bean으로 정의합니다.

생성된 클래스 코드는 동일한 속성 이름을 가진 소스 및 대상 클래스 아래처럼 보입니다.

@Component
public class EmployeeMapperImpl implements EmployeeMapper {

    @Override
    public Employee toEmployee(EmployeeDTO employeeDTO) {
        if ( employeeDTO == null ) {
            return null;
        }

        Employee employee = new Employee();

        employee.setDepartment( employeeDTO.getDepartment() );
        employee.setGender( employeeDTO.getGender() );
        employee.setId( employeeDTO.getId() );
        employee.setJobTitle( employeeDTO.getJobTitle() );
        employee.setJoinedDate( employeeDTO.getJoinedDate() );
        employee.setMobileNo( employeeDTO.getMobileNo() );
        employee.setName( employeeDTO.getName() );
        employee.setSalary( employeeDTO.getSalary() );

        return employee;
    }
}


이름이 다른 필드 매핑

대부분의 경우 소스 및 대상 클래스는 동일한 필드 이름을 가지지 않으므로 이제 이러한 필드를 매핑하는 방법에는 대상 필드 이름을 사용하는 @Mapping 주석이 있고 소스 필드 이름은 이러한 필드를 매핑합니다. @Mapping 주석의 필드에 대한 사용자 지정 매핑 논리를 제공할 수 있습니다.

@Mappings는 @Mappings 내부에 제공하는 것보다 더 많은 매핑 논리가 있는 경우 @Mapping 주석 그룹을 사용합니다.

public interface EmployeeMapper {

    @Mappings({
        @Mapping(target = "jobTitle", source = "title"),
        @Mapping(target = "joinedDate", source = "startingdate")
    })
    Employee toEmployee(EmployeeDTO employeeDTO);

}


중첩 콩 필드 매핑

여기에서 직원 클래스에 이름, 성별, 나이 및 주소 개체가 있는 개인 개체가 있는 예제를 보면 중첩된 개체 필드를 매핑하는 방법을 볼 수 있습니다.

target의 personal.address.streetaddress 필드 예제에 전체 경로를 제공해야 하므로 mapper는 개인 개체의 주소 내에서 streetaddress를 검색합니다.

@Mappings({ 
    @Mapping(target = "personal.name", source = "firstName"),
    @Mapping(target = "personal.gender", source = "gender"), 
    @Mapping(target = "personal.age", source = "age"),
    @Mapping(target = "personal.address.streetaddress", source = "dto.primaryAddr.line1"),
    @Mapping(target = "personal.address.city", source = "dto.primaryAddr.city"),
    @Mapping(target = "personal.address.postalcode", source = "dto.primaryAddr.postalCode") 
})
Employee toEmployee(EmployeeDTO dto);


사용자 지정 방법 매핑

어떤 경우에는 MapStruct에서 생성할 수 없는 한 유형에서 다른 유형으로의 특정 매핑을 수동으로 구현해야 할 수 있습니다. 이를 처리하는 한 가지 방법은 MapStruct에 의해 생성된 매퍼가 사용하는 다른 클래스에 사용자 지정 메서드를 구현하는 것입니다.

인터페이스에서 Java 8 기본 메소드를 정의하고 구현을 제공하십시오. @Named를 사용하여 메서드 이름을 지정합니다.

@Mapping 정의 소스 및 대상에서,qualifiedByName 속성에 @Named 메서드 이름을 지정하면 mapstruck이 코드를 생성하고 기본 메서드를 호출합니다.

package com.example.graphql.mapstruck;

import java.util.ArrayList;
import java.util.List;

@Mapper(componentModel = "spring")
public interface EmployeeMapper {

    @Mapping(target="primaryAddr",source ="personal.address",qualifiedByName = "addressdto" )
    EmployeeDTO toEmployeeDto(Employee employee);

    @Named("addressdto")
    default PrimaryAddr composeAddress(Address address) {

        PrimaryAddr primaryAddr=new PrimaryAddr();

        primaryAddr.setLine1(address.getStreetaddress());
        primaryAddr.setCity(address.getCity());
        primaryAddr.setPostalCode(address.getPostalcode());

        return primaryAddr;

    }

}


mapstruck이 위의 사용자 지정 메서드에 대한 매퍼 코드를 생성한 방법을 살펴보겠습니다. 생성된 매퍼 코드는 내부적으로 매핑 주소에 대한 사용자 지정 메서드를 호출합니다.

public class EmployeeMapperImpl implements EmployeeMapper {

    @Override
    public EmployeeDTO toEmployeeDto(Employee employee) {
        if ( employee == null ) {
            return null;
        }

        EmployeeDTO employeeDTO = new EmployeeDTO();

        employeeDTO.setPrimaryAddr( composeAddress( employeePersonalAddress( employee ) ) );

        return employeeDTO;
    }

    private Address employeePersonalAddress(Employee employee) {
        if ( employee == null ) {
            return null;
        }
        Personal personal = employee.getPersonal();
        if ( personal == null ) {
            return null;
        }
        Address address = personal.getAddress();
        if ( address == null ) {
            return null;
        }
        return address;
    }
}

좋은 웹페이지 즐겨찾기