아카이브

[DB][Prisma] foreign key를 이용해 일대다/일대일/다대다 관계 정의하기 본문

Backend/DB

[DB][Prisma] foreign key를 이용해 일대다/일대일/다대다 관계 정의하기

Rayi 2024. 8. 26. 13:47

일대다/일대일/다대다 관계를 구현하기 위해서는 '다'에 해당하는 테이블에 foreign key를 정의해야 합니다.

Prisma에서는 @relation 속성을 이용해 이 foreign key를 정의할 수 있습니다.

1. 일대다

 아래는 일대다 관계의 예시로, 사용자(User) 테이블과 주문(Order) 테이블의 관계를 나타내었습니다.

하나의 사용자는 여러 주문과 연결될 수 있고, 주문 테이블에 userId라는 foreign key 를 추가해 구분합니다.

아래는 각각 User와 Order의 Prisma model 코드입니다.

Order에는 User를 타입으로 하고 @relation 속성을 가지는 user 필드가 추가됩니다.

model User {
  id        String   @id @default(uuid())
  email     String   @unique
  firstName String
  lastName  String
  address   String
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt
  orders     Order[]		// 연결된 Order record들의 list
}
model Order {
  id        String      @id @default(uuid())
  status    OrderStatus @default(PENDING)
  createdAt DateTime    @default(now())
  updatedAt DateTime    @updatedAt
  user      User        @relation(fields: [userId], references: [id])
  userId    String
}

 

@relation 속성은 fieldsreferences를 매개변수로 받습니다.

fields는 현재 model(여기서는 Order)에서 foregin key로 사용될 필드입니다.

references는 참조하는 model(여기서는 User)에서 foreign key에 연결될 필드입니다.

 

User에는 한 record 당 참조 받는 foreign들을 나타내는 Orders 리스트가 추가됩니다. 

2. 일대일

 아래는 일대 관계의 예시로, 사용자(User) 테이블과 사용자 선호도(UserPreference) 테이블의 관계를 나타내었습니다.

하나의 사용자는 하나의 사용자 선호도와 연결될 수 있고, 사용자 선호도 테이블에 userId라는 foreign key 를 추가해 구분합니다.

일대다 관계와 마찬가지로 @relation을 사용하되,

foreign key가 서로 중복되는 값을 참조하면 안되기에 @unique 속성을 함께 표시합니다.

model User {
  id             String           @id @default(uuid())
  email          String           @unique
  firstName      String
  lastName       String
  address        String
  createdAt      DateTime         @default(now())
  updatedAt      DateTime         @updatedAt
  userPreference UserPreference?  // 연결된 UserPreference record (하나)
}
model UserPreference {
  id           String   @id @default(uuid())
  receiveEmail Boolean
  createdAt    DateTime @default(now())
  updatedAt    DateTime @updatedAt
  user         User     @relation(fields: [userId], references: [id])
  userId       String   @unique  // foreign key는 서로 중복될 수 없음 (일대일)
}

User는 한 record 당 최대 하나의 foreign key에게 참조받기 때문에,

일대일과 달리 list가 아닌 하나의 변수 UserPreference가 추가됩니다.

 

단, 이 때 userId는 @unique 조건이 있으면서 optional이 아니기 때문에(=반드시 값을 가져야 한다) 만약 User의 record가 UserPreference의 record보다 적으면 조건을 만족시킬 수 없습니다.

따라서 참조하는 foreign key(user)참조받는 필드(userPreference) 둘 중 하나를 optional로 지정해주어야 합니다.

User가 UserPreference보다 적으면 Unique와 non-optional이 지켜지지 않습니다.

3. 다대다

아래는 다대다 관계의 예시로, 사용자(User) 테이블과 상품(Product) 테이블의 관계를 나타내었습니다.

하나의 User는 여러 개의 Product를 참조할 수 있고, 하나의 Product 또한 여러 개의 User를 참조할 수 있습니다.

다대다는 일반적으로 각 테이블의 id mapping을 기록하는 juction table을 따로 만들어서 구현합니다.

하지만 Prisma에서는 따로 junction table을 만들 필요 없이 아래와 같이 처리할 수 있습니다.

model User {
  id             String           @id @default(uuid())
  email          String           @unique
  firstName      String
  lastName       String
  address        String
  createdAt      DateTime         @default(now())
  updatedAt      DateTime         @updatedAt
  savedProducts  Product[]  // Product에서 참조하는 id들의 list
}
model Product {
  id          String      @id @default(uuid())
  name        String
  description String?
  category    Category
  price       Float
  stock       Int
  createdAt   DateTime
  updatedAt   DateTime
  saveUsers   User[]  // User에서 참조하는 id들의 list
}

@relation의 경우 user User 구문까지 입력한 뒤 포맷팅(Shift + alt + f)을 하면 자동으로 완성됩니다.

 

 

728x90
Comments