CodeLap - enum 클래스를 @ElementCollection으로 매핑하기.
@ElementCollection은 엔티티에 컬렉션을 저장하기 위해 사용하는 어노테이션이다.
RDB에서는 테이블에 컬렉션을 저장할 수 있는 기능을 지원하지 않기때문에, ORM에서는 객체에 컬렉션을 저장할 수 있는것 처럼 보이지만, 실제로는 스키마에 테이블을 하나 더 만들어서 관리한다.
JPA에서는 @ElementCollection을 통해 해당 엔티티에서 컬렉션을 관리한다고 알려줄 수 있다.
@ElementCollection
@Enumerated(STRING)
private List<TechStack> techStackList;
create table study_tech_stack_list
(
study_id bigint not null,
tech_stack_list varchar(255)
);
alter table study_tech_stack_list
add constraint FK9f7m49a8kckvtr1s1xxk79ldp foreign key (study_id) references study (id);
해당 프로젝트에서는 플라이웨이로 DB 버전관리를 하는데, techStackList가 따로 테이블로 생성되고, 스터디라는 부모 엔티티에 의해 관리되는 걸 알 수 있다.
cascade 옵션이 default 이기 때문에, 부모 데이터가 삭제될 시 해당 테이블의 데이터도 함께 삭제된다.
@Embeddable
public enum TechStack {
JavaScript,
TypeScript,
React,
Vue,
Svelte,
Nextjs,
Nodejs,
Java,
Spring,
Go,
Nestjs,
Kotlin,
Express,
MySQL,
MongoDB,
Python,
Django,
php,
GraphQL,
Firebase,
Flutter,
Swift,
ReactNative,
Unity,
AWS,
Kubernetes,
Docker,
Git,
Figma,
Zeplin,
Jest
}
Enum 클래스에서 Embeddable로 TechStack의 수많은 컬럼들을 하나의 객체로 관리하려고 했었는데,
예외가 발생했다. com.codelap.common.study.domain.Study.techStackList 라는 컬렉션에 대한 persister implementor를 인스턴스화 할 수 없다는 오류메세지였다.
오류가 발생한 원인은 아마 내가 매핑한 컬렉션에 문제가 생긴게 자명했다.
결론부터 말하자면, 오류는 @Embeddable 어노테이션 때문에 발생한 것이었다. 이늄 클래스가 아닌 일반 클래스에서는 ElementCollection을 Embeddable 어노테이션과 함께 사용해 하나의 객체로 관리할 수 있는데, 이늄 클래스에서는 안되는 것이었다.
내가 enum 클래스에 대한 이해도가 조금 부족했던 것 같다.
@Embeddable은 엔티티의 속성을 클래스로 분리할 때 사용된다. 따라서 @Embeddable은 일반적으로 객체 컴포지션을 위해 사용된다.
반면에, Enum 클래스는 상수 집합으로 사용되므로 객체 컴포지션과 관련이 없다. 따라서 @Embeddable을 사용할 수가 없다.
프로젝트를 통해 배우는것이 참 많은 것 같다.