Framework/SpringBoot

[SpringBoot3] 엔티티 상속관계에서 @Builder 적용

  • -
상속관계에서 Builder를 적용했을 때 발생한 이슈에 대해 작성한 글입니다.

발생 배경

엔티티에 @Builder 어노테이션을 사용하였습니다.

@Entity
@DiscriminatorValue("PRODUCT")
@Getter
@Builder
@AllArgsConstructor
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Product extends Item {

    @Enumerated(EnumType.STRING)
    @Column(nullable = false)
    private ProductStatus status;

    // ...
}

 

다만 Product의 부모 엔티티인 Item에도 @Builder 어노테이션이 있는데요

@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "dtype", discriminatorType = DiscriminatorType.STRING)
@Getter
@Builder
@AllArgsConstructor
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Item {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @ManyToOne(targetEntity = User.class, fetch = FetchType.LAZY)
    @JoinColumn(name = "user_id")
    private User user;
    
    // ..
}


이 때 아래와 같은 에러가 발생했습니다.

error: builder() in Product cannot hide builder() in Item
@Builder
^
  return type ProductBuilder is not compatible with ItemBuilder

 

문제

 

에러 메세지를 보면 유추할 수 있듯이, 이 에러는 상속 관계의 엔티티에서 빌더를 잘 못 사용하여 발생한 에러입니다.

 

@Builder 어노테이션을 사용하여 초기화할 때, 자식 클래스에서 부모 클래스의 필드를 발견하지 못하며 따라 자식 클래스를 초기화 할 때 부모 클래스의 필드를 초기화 할 수 없어 발생하는 에러입니다.

 

해결

이 문제를 @SuperBuilder 어노테이션을 통해 해결할 수 있습니다.@SuperBuilder를 사용하면 자식 클래스에서 빌더를 생성할 때 부모 클래스의 필드와 메서드가 자동으로 포함됩니다. 따라 부모의 클래스를 초기화할 수 있게 됩니다.

 

@SuperBuilder 어노테이션을 사용하여 코드를 수정했습니다.

 

Product.java

@Entity
@DiscriminatorValue("PRODUCT")
@Getter
@SuperBuilder
@AllArgsConstructor
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Product extends Item {

    @Enumerated(EnumType.STRING)
    @Column(nullable = false)
    private ProductStatus status;

    // ...
}

 

Item.java

@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "dtype", discriminatorType = DiscriminatorType.STRING)
@Getter
@SuperBuilder
@AllArgsConstructor
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Item {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @ManyToOne(targetEntity = User.class, fetch = FetchType.LAZY)
    @JoinColumn(name = "user_id")
    private User user;
    
    // ..
}

 

 

Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.