Spring

Mapstruct & Lombok 적용

빠빠담 2021. 4. 16. 02:20
반응형

인터넷 자료를 보고 Mapstruct를 적용하려고 하다가

하나가 되면 하나가 안되고 또 하나가 되면 하나가 안되고

그래서 내가 다시 정리해본다.

 

1. 디펜던시 적용

    ext {
        mapstructVersion = "1.3.0.Final"
    }

    dependencies {
        compileOnly 'org.projectlombok:lombok'

        implementation "org.mapstruct:mapstruct:${mapstructVersion}"

        annotationProcessor "org.mapstruct:mapstruct-processor:${mapstructVersion}"
        annotationProcessor 'org.projectlombok:lombok'
        annotationProcessor 'org.projectlombok:lombok-mapstruct-binding:0.2.0'

다른 부분은 괜찮았는데 가장 아래부분에 lombok-mapstruct-binding 을 추가하지 않아서 한참을 해맸다.

Setter가 아닌 Builder를 사용하여 Mapstruct를 사용하기 위해서 해당 부분이 필요한것으로 확인된다.

 

2. 롬복 설정 적용

lombok.addLombokGeneratedAnnotation = true
lombok.anyConstructor.addConstructorProperties = true

lombok.config 파일을 프로젝트 최상위 폴더에 위치하고 위의 설정을 적용하자

이 또한 Mapstruct에서 객체 생성을 Builder를 통해 생성하기 위한 설정이다.

 

3. 데이터 정의

@Getter
@FieldDefaults(level = AccessLevel.PRIVATE)
public class DataDto {

    @Builder(builderMethodName = "of")
    public DataDto(String name, String email, String birth) {
        this.name = name;
        this.email = email;
        this.birth = birth;
    }

    String name;
    String email;
    String birth;
}
@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@FieldDefaults(level = AccessLevel.PRIVATE)
public class DataEntity {

    @Builder(builderMethodName = "of")
    public DataEntity(String name, String email, int ageGroup) {
        this.name = name;
        this.email = email;
        this.ageGroup = ageGroup;
    }

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    Long id;

    String name;
    String email;
    int ageGroup;
}

 

dto를 entity로 

entity를 dto로 이제 변환시켜보자 

mapstruct를 사용하여서.

 

4. Mapper 객체 정의

public interface GenericMapper<D, E> {

    D toDto(E entity);

    E toEntity(D dto);

    @BeanMapping(nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE)
    void updateFromDto(D dto, @MappingTarget E entity);

}

공통 매퍼를 정의 하고 하위 타입을 정의 해보자

@Mapper(componentModel = "spring")
public interface DataMapper extends GenericMapper<DataDto, DataEntity> {
    DataMapper instance = Mappers.getMapper(DataMapper.class);
}

 

componentModel = "spring" 을 통해 스프링 컨테이너에 객체로 관리해도 되고
인스턴스를 만들어 사용해도 된다 편한것을 사용하자

 

이후 그레이들 빌드를 통해 생성된 구현 객체를 확인해보자

@Generated(
    value = "org.mapstruct.ap.MappingProcessor",
    date = "2021-04-16T02:07:50+0900",
    comments = "version: 1.3.0.Final, compiler: javac, environment: Java 11.0.10 (Ubuntu)"
)
@Component
public class DataMapperImpl implements DataMapper {

    @Override
    public DataDto toDto(DataEntity entity) {
        if ( entity == null ) {
            return null;
        }

        DataDtoBuilder dataDto = DataDto.of();

        dataDto.name( entity.getName() );
        dataDto.email( entity.getEmail() );

        return dataDto.build();
    }

    @Override
    public DataEntity toEntity(DataDto dto) {
        if ( dto == null ) {
            return null;
        }

        DataEntityBuilder dataEntity = DataEntity.of();

        dataEntity.name( dto.getName() );
        dataEntity.email( dto.getEmail() );

        return dataEntity.build();
    }

    @Override
    public void updateFromDto(DataDto dto, DataEntity entity) {
        if ( dto == null ) {
            return;
        }
    }
}

위와 같이 인터페이스를 구현한 객체를 생생해주었음을 확인할 수 있다.

 

DataEntity dataEntity = DataMapper.instance.toEntity(dto);

변환완료!

 

 

아래는 mapstruct가 갑자기 널포인트 익셉션을 발생시켜 확인 해본 결과 

mapstruct 버전을 올려주자 1.4.1.Final

 

stackoverflow.com/questions/65112406/intellij-idea-mapstruct-java-internal-error-in-the-mapping-processor-java-lang

 

IntelliJ Idea mapstruct java: Internal error in the mapping processor: java.lang.NullPointerException

After upgrading to the version 2020.3 of Idea i get a NullPointerException for the mapping processor. If anybody has a clue... Thank you!

stackoverflow.com

 

반응형