🐳 문제
계층형 데이터 구조를 저장하기 위해 Custom Closure Table을 구현하는데
PK값이 없다는 아래와 같은 에러가 발생했다.
MissingPrimaryColumnError: Entity "CategoryClosure" does not have a primary column. Primary column is required to have in all your entities. Use @PrimaryColumn decorator to add a primary column to your entity.
📋 Entity 코드
작성한 Entity 코드는 아래와 같다.
@Entity()
@Unique(['ancestorId', 'descendantId'])
export class CategoryClosure {
@Column({ comment: '조상 카테고리 PK', type: 'integer' })
@ApiProperty({ description: '조상 카테고리 PK', type: 'number' })
ancestorId: number;
@Column({ comment: '자손 카테고리 PK', type: 'integer' })
@ApiProperty({ description: '자손 카테고리 PK', type: 'number' })
descendantId: number;
@Column({ comment: '카테고리 뎁스', type: 'integer', default: 0 })
@ApiProperty({ description: '카테고리 뎁스', type: 'number', example: 0 })
depth: number;
@ManyToOne(() => Category)
@JoinColumn({ name: 'ancestorId' })
ancestor: Category;
@ManyToOne(() => Category)
@JoinColumn({ name: 'descendantId' })
descendant: Category;
}
Primary Column으로 지정한 Column은 없지만 Unique 키를 지정했기 때문에 괜찮을 것이라고 생각했다.
하지만 처음에 봤던 것과 같은 MissingPrimaryColumnError 에러가 발생했다.
🐳 해결방안
Unique 키 값을 지정해주는 것이 아니라 PrimaryColumn을 지정해 주어야 한다.
그리고 이때 PrimaryColumn 데코레이터를 여러개 사용하는 경우 복수 Column을 묶어서 하나의 PK로 사용한다.
코드를 살펴보자
📋 변경된 Entity 코드
@Entity()
// Unique 키 값이 아닌 PrimaryColumn 값을 지정해 주어야 하므로 삭제한다.
// @Unique(['ancestorId', 'descendantId'])
export class CategoryClosure {
// 기존에 Column 데코레이터 -> PrimaryColumn 으로 수정
@PrimaryColumn({ comment: '조상 카테고리 PK', type: 'integer' })
@ApiProperty({ description: '조상 카테고리 PK', type: 'number' })
ancestorId: number;
// 기존에 Column 데코레이터 -> PrimaryColumn 으로 수정
@PrimaryColumn({ comment: '자손 카테고리 PK', type: 'integer' })
@ApiProperty({ description: '자손 카테고리 PK', type: 'number' })
descendantId: number;
@Column({ comment: '카테고리 뎁스', type: 'integer', default: 0 })
@ApiProperty({ description: '카테고리 뎁스', type: 'number', example: 0 })
depth: number;
@ManyToOne(() => Category)
@JoinColumn({ name: 'ancestorId' })
ancestor: Category;
@ManyToOne(() => Category)
@JoinColumn({ name: 'descendantId' })
descendant: Category;
}
📋 결과 확인
우리가 원하는 대로 ancestorId + descendantId를 PK 값으로 사용하고 있는 것을 확인할 수 있다 !!
문제 해결 !!!