개요
Generic이 구성된 DTO에 Builder, SuperBuilder를 적용하면서 헤맸던 부분을 기록한다.
Builder
@ToString
@Builder
public class OuterDTO<T> {
private int id;
private T inner;
}
위와 같이 OuterDTO에 Generic을 구성하고, inner 필드에 들어갈 DTO는 아래와 같이 작성해 보자.
@ToString
어노테이션은 테스트 시 출력 결과를 확인하기 위해 붙여두었다.
@ToString
@Builder
public class InnerDTO {
private String name;
}
이후 아래와 같이 메소드를 구성하고 실행해 보자.
제네릭이 설정된 OuterDTO를 Builder로 적용할 때에는 builder() 앞부분에 제네릭으로 들어갈 클래스를 넣어주도록 구성하면 된다.
public void test() {
InnerDTO innerDTO = InnerDTO.builder()
.name("name1")
.build();
System.out.println(innerDTO);
OuterDTO<InnerDTO> outerDTO = OuterDTO.<InnerDTO>builder()
.id(1)
.inner(innerDTO)
.build();
System.out.println(outerDTO);
}
SuperBuilder
SuperBuilder는 상속받은 클래스의 필드까지 Builder 패턴을 적용하기 위해 사용된다.
이 때는 상위 클래스 및 하위 클래스 모두 @SuperBuilder
어노테이션을 붙여주어야 한다.
먼저 상위 클래스를 아래와 같이 작성해 보자.
@ToString
@SuperBuilder
public class ParentDTO {
private int parentId;
}
그리고 InnerDTO에서 ParentDTO를 상속받고, @Builder
를 @SuperBuilder
로 바꿔준다.
상위 클래스를 좀 더 명확히 출력하기 위해 toString을 오버라이딩하였다.
@SuperBuilder
public class InnerDTO extends ParentDTO {
private String name;
@Override
public String toString() {
return super.toString() + "\n"
+ "InnerDTO(name=" + name + ")";
}
}
위처럼 구성하였으면 @SuperBuilder
가 잘 동작하는지 확인해 보자.
public void test() {
InnerDTO innerDTO = InnerDTO.builder()
.parentId(1)
.name("name1")
.build();
System.out.println(innerDTO);
}
@SuperBuilder
가 잘 동작하는 것까지 확인했으니, 이제 제네릭을 적용해 보자.
먼저 InnerDTO는 다시 기존 구조로 원복한다.
@ToString
@Builder
public class InnerDTO {
private String name;
}
이제 OuterDTO에 @SuperBuilder
를 구성해 보자.
이때 상속받는 상위 클래스에도 동일한 제네릭을 설정해 줘야 한다.
@SuperBuilder
public class OuterDTO<T> extends ParentDTO<T> {
private int id;
private T inner;
@Override
public String toString() {
return super.toString() + "\n"
+ "OuterDTO(id=" + id + ", inner=" + inner + ")";
}
}
@ToString
@SuperBuilder
public class ParentDTO<T> {
private int parentId;
}
다시 아래처럼 메소드를 구성하고 잘 동작하는지 확인해 보자.
public void test() {
InnerDTO innerDTO = InnerDTO.builder()
.name("name1")
.build();
System.out.println(innerDTO);
OuterDTO<InnerDTO> outerDTO = OuterDTO.<InnerDTO>builder()
.parentId(1)
.id(2)
.inner(innerDTO)
.build();
System.out.println(outerDTO);
}
정상적으로 잘 적용된 것을 확인할 수 있다.
@SuperBuilder
어노테이션은 상속된 필드도 Builder에 포함하여 빌더 클래스를 생성하는데,
제네릭을 사용할 때에는 상위 클래스와 하위 클래스의 필드가 동일한 제네릭 타입으로 설정되어 있어야만 Lombok이 빌더 클래스를 생성할 때 자동으로 상속된 필드를 포함한다.
마무리
사실 이 포스팅은 SuperBuilder에서 상속과 제네릭을 함께 사용할 수 없다는 내용을 기록하려고 한 것인데, @SuperBuilder
어노테이션을 DeLombok해서 코드를 뜯어보기도 하고 포스팅을 작성하기 위해 관련 내용을 더 공부하다 보니 사용하는 방법을 알게 되어 사용 방법에 대한 포스팅으로 바뀌었다.
이미 아는 내용이어도 기록으로 정리하는 것의 중요성을 다시금 느낀다.
'Java & Spring' 카테고리의 다른 글
[JAVA] LocalDate로 한국식 월 주차 구하기 (6) | 2023.07.27 |
---|---|
[JAVA] Calendar로 한국식 월 주차 구하기 (0) | 2023.07.24 |
[Spring] JPA 중복 Insert 방지하기 (0) | 2023.07.18 |
[JAVA] poi에서 SXSSFWorkbook 사용 시 NullPointerException이 발생하는 경우 (0) | 2023.04.28 |
[JAVA] poi에서 엑셀을 다룰 때 발생하는 여러가지 오류 (1) | 2023.04.05 |