상속관계에서 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;
// ..
}
'Framework > SpringBoot' 카테고리의 다른 글
[Spring] VO와 BO, DAO, DTO란 무엇인가 (1) | 2024.03.24 |
---|---|
[SpringBoot3] 스프링부트와 Swagger 연결방법 (0) | 2024.03.21 |
[SpringBoot] application.properties에서 DB 정보 등 민감한 내용 분리하기 (0) | 2024.03.13 |
[Spring] MappedSuperclass 사용하기 (0) | 2024.02.14 |
[SpringBoot] 데이터베이스 스키마 자동 생성 옵션에 대해 알아보자 / spring.jpa.hibernate.ddl-auto (0) | 2023.12.26 |