๐ ๋ฏธ๋์ ๋ณธ์ธ์ ์ํด ์ ๋ฆฌํ๋ prisma ๐
sequelize
์ ๊ฐ์ ORM
์
๋๋ค.
ORM
: Object Relational Mapping
์ผ๋ก JavaScript
์ ๊ฐ์ฒด๋ฅผ Database
์ ํ
์ด๋ธ ํน์ ์คํค๋ง์ ์ฐ๊ฒฐํด์ SQL๋ฌธ ๋ณด๋ค ์ฝ๊ณ ํธํ๊ฒ DB๋ฅผ ์ปจํธ๋กคํ ์ ์๋ ๋ฐฉ์์
๋๋ค.JS
์ class
๋ TS
์ interface
๋ก ํํ์ ์์ฑ๋ค์ ์ ์ํด์ฃผ๋ฉด ๊ทธ๊ฒ์ ๋ง๊ฒ ์๋์ ์ผ๋ก SQL
๋ฌธ์ ์์ฑํด์ Database
๋ฅผ ๊ด๋ฆฌํด์ฃผ๋ ๊ฒ์ผ๋ก ์๊ณ ์์ต๋๋ค.
ORM
์ ์ฅ์ ์ ๊ตณ์ด ๋ณต์กํ SQL
์ ๋ํด ์์ธํ๊ฒ ์ดํดํ์ง ์์๋ ๋๋ฉฐ(๋ฌผ๋ก ์ด๋์ ๋๋ ์๊ณ ์ฌ์ฉํด์ผํ๋ค๊ณ ์๊ฐํจ), CRUD
๊ทธ๋ฆฌ๊ณ JOIN
๊ฐ์ ๋ณต์กํ ์ฐ์ฐ์ ๊ฐ๋จํ๊ฒ ํด๊ฒฐํด์ฃผ๋ ๋ฉ์๋๋ฅผ ๋ฏธ๋ฆฌ ๊ตฌํํด๋จ๊ธฐ ๋๋ฌธ์ ์ฝ๊ฒ ๋ฐ์ดํฐ๋ฅผ ๊ด๋ฆฌํ ์ ์์ต๋๋ค.
npm i -D prisma
npm i @prisma/client
npx prisma init
/prisma/schema.prisma
์ .env
๊ฐ ์์ฑ๋ฉ๋๋ค.
/prisma/schema
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "mysql"
url = env("DATABASE_URL")
}
model User {
id Int @id @default(autoincrement())
email String @unique
name String?
}
.env
DATABASE_URL="mysql://testUser:test@localhost:3306/testDB"
DATABASE_URL="mysql://<์ ์ ๋ช
>:<๋น๋ฐ๋ฒํธ>@<ํธ์คํธ>:<port>/<DB๋ช
>
prisma
์ ์ธํ
์ ์
๋ ฅํ๋ ํ์ผ์
๋๋ค.
# prisma์ Database๋ฅผ ์ฐ๊ฒฐํ๋ ๋ฐฉ๋ฒ์ ์ค์ ํ๋ ๋ถ๋ถ์
๋๋ค.
datasource db {
provider = "mysql"
url = env("DATABASE_URL")
referentialIntegrity = "prisma"
}
#
generator client {
provider = "prisma-client-js"
previewFeatures = ["referentialIntegrity"]
}
# Database์ ํ
์ด๋ธ์ ํํ๋ฅผ ๋ช
์
# user์ post ๊ด๊ณ ( 1 : N )
model User {
id Int @id @default(autoincrement())
name String
phone Int? @unique
email String? @unique
avatar String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
posts Post[]
}
model Post {
id Int @id @default(autoincrement())
content String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
userId Int
}
@relation
์ ์ ์ํ๋ ๋ชจ๋ธ์ foreign key
๊ฐ ์์ฑ๋ฉ๋๋ค.1 : 1
# 1 : 1 ๊ด๊ณ์ด๋ฏ๋ก User or Profile์ค์ foreign key๋ฅผ ์์ฑํ ์์น๋ ์ ํํ ์ ์์ ( @relation ์์น )
model User {
id Int @id @default(autoincrement())
profile Profile?
}
model Profile {
id Int @id @default(autoincrement())
name String
user User @relation(fields: [userId], references: [id])
userId Int @unique
}
1 : N
model User {
id Int @id @default(autoincrement())
email String
name String?
# vscode์ prismaํ๋ฌ๊ทธ์ธ์ ์ค์นํ์ ๊ฒฝ์ฐ์
# ์๋ ์ฝ๋๋ถํฐ ์
๋ ฅํ๋ฉด ์๋์ผ๋ก Post์ ๊ด๊ณ์ค์ ์ฝ๋๋ฅผ ์
๋ ฅํด์ค๋ค.
posts Post[]
}
model Post {
id Int @id @default(autoincrement())
contents String
User User? @relation(fields: [userId], references: [id])
userId Int?
}
N : M
# ๋ฌต์์ N : M
# @relation("MyTable")์ ์ค๊ฐ ํ
์ด๋ธ ์ด๋ฆ ์ง์ ( _MyTable )
# ์๋ต์ _PostToCategory์ ๊ฐ์ ๋ช
์นญ์ ์ค๊ฐ ํ
์ด๋ธ์ด ์์ฑ๋จ
model Post {
id Int @id @default(autoincrement())
contents String
categories Category[] @relation("MyTable")
}
model Category {
id Int @id @default(autoincrement())
category String
posts Post[] @relation("MyTable")
}
# ๋ช
์์ N : M
model Post {
id Int @id @default(autoincrement())
title String
categories PostCategory[]
}
model Category {
id Int @id @default(autoincrement())
category String
posts PostCategory[]
}
model PostCategory {
Post Post @relation(fields: [postId], references: [id])
postId Int
Category Category @relation(fields: [categoryId], references: [id])
categoryId Int
@@id([postId, categoryId])
}
1 : N
๊ด๊ณ๋ฅผ ๊ฐ์ง ๋# user์ message๊ฐ ๋ ๋ฒ 1 : N๊ด๊ณ๋ฅผ ๊ฐ์ง๋ ๊ฒฝ์ฐ, "name"์ผ๋ก ๊ตฌ๋ถ
model User {
id Int @id @default(autoincrement())
email String
name String?
sentMessage Message[] @relation("sent")
receivedMessage Message[] @relation("received")
}
model Message {
id Int @id @default(autoincrement())
message String
sent User? @relation(name: "sent", fields: [sentId], references: [id])
sentId Int?
received User? @relation(name: "received", fields: [receivedId], references: [id])
receivedId Int?
}
create
: ์ฐ๊ด๋ ํ
์ด๋ธ์ ๋ฐ์ดํฐ ์์ฑawait prisma.user.create({
data: {
name: "admin",
email: "admin@naver.com",
posts: {
create: {
contents: "์ฒซ ๋ฒ์งธ ๊ฒ์๊ธ",
},
},
},
});
connect
: ์ด๋ฏธ ์์ฑ๋ ๋ฐ์ดํฐ ์ฐ๊ฒฐ// async ํจ์ ๋ด๋ถ์ ์ฝ๋๋ผ ๊ฐ์
const createdPost = await prisma.post.create({
data: {
contents: "์ฒซ ๋ฒ์งธ ๊ฒ์๊ธ",
},
});
await prisma.user.create({
data: {
name: "admin",
email: "admin@naver.com",
posts: {
connect: {
id: createdPost.id,
},
},
},
});
include
: ํฌํจํด์ ๊ฐ์ ธ์ค๊ธฐ// ๊ธฐ๋ณธ ํํ ( post์ ๋ชจ๋ row๋ค์ ๊ฐ์ ธ์ด )
const usersWithPosts = await prisma.user.findMany({
include: {
posts: true,
},
});
// select์ด์ธ์ ๋ค๋ฅธ ์กฐ๊ฑด๋ค๋ ์ฌ์ฉํ ์ ์์ ( post์ id, name๋ง ๊ฐ์ ธ์ด )
const usersWithPosts = await prisma.user.findMany({
include: {
posts: {
select: {
id: true,
name: true,
},
},
},
});
npx prisma db push
๋ก ํ
์ด๋ธ ์์ฑ ์ ์๋์ ์ผ๋ก ํ์
์ ๋ง๋ค์ด์ค๋๋ค.
๋ง๋ค์๋ง์ import
ํ๋ ค๋ฉด VSCode์์ ์ธ์์ ๋ชปํ๋๋ฐ ๊ทธ๋๋ ์ง์ ํ์ผ์ ๋ค์ด๊ฐ๋ค๊ฐ ๋์ค๋ฉด VSCode์์ ํ์
์ ์ธ์ํฉ๋๋ค.
model User {
id Int @id @default(autoincrement())
name String @db.VarChar(20)
email String
posts Post[]
}
model Post {
id Int @id @default(autoincrement())
User User? @relation(fields: [userId], references: [id])
userId Int?
}
// node_modules/.prisma/client/index.d.ts
export type User = {
id: number
name: string
email: string | null
}
export type Post = {
id: number
userId: number
}
// import { Product } from "@prisma/client";
<DB๋ช
>CreateInput
์ฌ์ฉ ์์let user: Prisma.UserCreateInput = {
name: "",
email: "aa",
};
const exUser = await prisma.user.create({
data: user,
});
๋ชจ๋ user
์ post
๋ผ๋ ํ
์ด๋ธ์ด ์๋ค๊ณ ๊ฐ์ ํ๊ณ ์์ฑํ๊ฒ ์ต๋๋ค.
prisma.user.create()
const createdUser = await prisma.user.create({
data: {
name: "john",
email: "j@naver.com"
},
});
prisma.user.createMany()
const count = await prisma.user.createMany({
data: [
{ name: "apple", email: "a@naver.com" },
{ name: "blue", email: "b@naver.com" },
{ name: "color", email: "c@naver.com" },
// ...
],
});
console.log(count.count); // 3
prisma.user.findUnique()
const exUser = await prisma.user.findUnique({
// ์ ๋ํฌํ ๊ฐ๋ง ๊ฒ์์กฐ๊ฑด์ผ๋ก ์ฌ์ฉํ ์ ์์ต๋๋ค. ( type์ด ์๋์ผ๋ก ๋ง๋ค์ด์ ธ ์์ด์ ๊ฒ์ํ ์ ์๋ row๋ฅผ ๋ณด์ฌ์ค )
where: {
id: 1,
},
});
// ๋ง์ฝ @@unique([email, name])๊ฐ์ ํ์์ผ๋ก ๋ง๋ค์๋ค๋ฉด ์๋์ ๊ฐ์ด ์ฌ์ฉํด์ผํฉ๋๋ค.
// ํน์ @@unique([email, name], name: "yourName")์ฒ๋ผ ๋ง๋ค์๋ค๋ฉด "email_name"๋์ "yourName"์ ์ฌ์ฉํ๋ฉด ๋ฉ๋๋ค.
const exUser = await prisma.user.findUnique({
where: {
email_name: {
email: "a@naver.com",
name: "a",
},
},
});
prisma.user.findMany()
// ๋ชจ๋ ๋ฐ์ดํฐ ๊ฐ์ ธ์ค๊ธฐ
const allUser = await prisma.user.findMany();
// ํน์ ๋ฐ์ดํฐ ๋ชจ๋ ๊ฐ์ ธ์ค๊ธฐ
const allUser = await prisma.user.findMany({
where: {
// ...
},
});
prisma.user.findFirst()
// ์กฐ๊ฑด์ ๋ง์กฑํ๋ ์ฒซ ๋ฒ์งธ ๋ฐ์ดํฐ๋ง ๊ฐ์ ธ์ค๊ธฐ
const allUser = await prisma.user.findFirst({
where: {
// ...
},
});
prisma.user.updateMany()
const updateUsers = await prisma.user.updateMany({
where: {
// ...
},
data: {
// ...
},
})
prisma.user.upsert()
// ์์ผ๋ฉด ์์ฑ, ์์ผ๋ฉด ์
๋ฐ์ดํธ
const upsertUser = await prisma.user.upsert({
where: {
// ...
},
update: {
// ...
},
create: {
// ...
},
})
prisma.user.delete()
const deleteUser = await prisma.user.delete({
where: {
email: 'bert@prisma.io',
},
});
prisma.user.delete()
// ์กฐ๊ฑด์ ๋ง์กฑํ๋ ์ผ๋ถ๋ถ ์ญ์
const deleteUsers = await prisma.user.deleteMany({
where: {
email: {
contains: 'prisma.io',
},
},
});
// ์ ์ฒด ์ญ์
const deleteUsers = await prisma.user.deleteMany({});
select
: ํน์ ํ๋ ์ ํ or ๊ด๊ณ๋ ํ
์ด๋ธ ๋ฐ ํ
์ด๋ธ์ ํน์ ํ๋ ์ ํinclude
: ๊ด๊ณ๋ ํ
์ด๋ธ ์ ํorderBy
: ์ ๋ ฌcontains
: ํฌํจ๋๊ฒ ์ฐพ๊ธฐdisconnect
: ํน์ ๋ ์ฝ๋ ๊ด๊ณ ๋๊ธฐset
: ๋ชจ๋ ๋ ์ฝ๋ ๊ด๊ณ ๋๊ธฐdeleteMany
: ๋ชจ๋ or ํน์ ๋ ์ฝ๋ ์ญ์ update
: ํน์ ๋ ์ฝ๋ ์์ upsert
: ํน์ ๋ ์ฝ๋ ์์ฑ or ์์ @@map("posts")
: ์ค์ ํ
์ด๋ธ๋ช
์ ๋ฐ๋์ง๋ง prisma
์์ ์ฌ์ฉํ๋ ๋ช
์นญ์ ๋ฐ๋์ง ์์@id
, @default()
, @default(autoincrement())
, @unique
@@id([id, email])
: id
์ email
์ ํฉ์ณ์ primary key
๋ก ์ง์ @@unique([email, name])
: email
๊ณผ name
ํฉ์ณ์ unique key
๋ก ์ค์ @@index([email, name])
: email
๊ณผ name
ํฉ์ณ์ index
๋ก ์ค์
@@id
,@@unique
์ ๋ฐฐ์ด ๋ด๋ถ์ ํ๋ฒ์ ์ ์ ๊ฒฝ์ฐ ๊ฐ๊ฐ์ด ์๋๋ผ ๋ ๊ฐ์ง๋ฅผ ํฉ์ณ์ ์ธ๋ฑ์ค๋ก ์ง์ ํฉ๋๋ค.
now()
: ํ์ฌ ์๊ฐuuid()
: UUID
์ฌ์๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ๊ณ ์ ํ ์๋ณ์ ์์ฑautoincrement()
@relation()
fields: []
references: []
onDelete: Cascade
onUpdate: Cascade