spring

[spring] @SuperBuilder 적용에서 발생한 문제와 해결

hseoky 2024. 3. 23. 23:28
728x90

 

현재 진행 중인 프로젝트에서 @SuperBuilder를 적용하며 문제상황이 발생하였고, 해결과정을 정리해보려 한다.

❓문제상황


문제 상황의 엔티티 구조는 다음과 같았다.

BaseEntity

@Getter
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public abstract class BaseEntity {

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

  @CreatedDate
  @Column(updatable = false)
  private LocalDateTime createdAt;

  @LastModifiedDate
  private LocalDateTime modifiedAt;
}

Parent

@Getter
@SuperBuilder
@MappedSuperclass
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor
public abstract class Parent extends BaseEntity {

  private String a;
}

Child

@Entity
@Getter
@SuperBuilder
@NoArgsConstructor
public class Child extends Parent {

  private String b;
}

Child 엔티티는 Parent 엔티티를 상속받고, Parent 엔티티는 BaseEntity를 상속받는다.

이 상황에서 Child 엔티티에 빌더 패턴을 생성하기 위해 ChildParent@SuperBuilder 애너테이션을 추가해 주었더니 아래와 같은 에러가 발생했다.

https://stackoverflow.com/questions/59626796/lomboks-superbuilder-error-java-cannot-find-symbol

 

Lombok's @SuperBuilder - Error java: cannot find symbol

I've been using Lombok with IntelliJ for a while now. I have installed newest (v. 0.28) Lombok plugin, enabled annotation processing and added a Lombok dependency (v. 1.18.10) in pom.xml. It all wo...

stackoverflow.com

 

위 stackoverflow 사이트에서 해당 오류와 관련된 해결책으로 BaseEntity에도 @SuperBuilder를 추가하는 방법이 있었다.

하지만 위 BaseEntity에는 Id와 생성시간, 수정시간 등 빌더패턴에 포함시키고 싶지 않은 필드들이 존재 하였고 다른 방법을 생각하게 되었다.

📌해결방법


생성자에 @SuperBuilder를 붙이는 방법도 생각해 보았지만 해당 애너테이션은 생성자에는 적용할 수 없었다.

결국 @SuperBuilder를 포기하고 다음과 같은 방법으로 Child 엔티티의 빌더를 생성했다.

@Entity
@Getter
@NoArgsConstructor
public class Child extends Parent {

  private String b;

  @Builder
  public Child(String a) {
    super(a);
    this.rating = rating;
  }
}

Parent를 상속받는 엔티티에 위와 같이 빌더를 적용할 생성자를 직접 생성해 주어야 했지만 BaseEntity의 필드 값이 엔티티 객체의 초기화에 이용되는 상황을 방지할 수 있었다.

🧐테스트 코드

@Test
void childBuilderTest() {
    Child child = Child.builder()
        .a("parent field")
        .b("child field")
        .build();

    em.persist(child);
}

 

실제 엔티티로 테스트한 결과는 아래와 같다

 

728x90