Typescript 製 ORM の Prisma の主要機能を触ってみたいと思います。
チュートリアルのデータベースを新規に作成する開発パターン をベースに機能を試して行きます。
初期設定
- 必要なものを install する
- devDependencies
typescript
prisma
ts-node
@types/node
- dependencies
@prisma/client
- devDependencies
-
npx prisma init
する - DB の接続情報を設定する
migrate
こちらを参考に schemaファイル (schema.prisma) に user, post, profile の schema を記載します。
次に上記を参考に npx prisma migrate dev --name init
を実行します。
$ npx prisma migrate dev --name init
Environment variables loaded from .env
Prisma schema loaded from prisma/schema.prisma
Datasource "db": MySQL database "mydb" at "db:3306"
- Drift detected: Your database schema is not in sync with your migration history.
The following is a summary of the differences between the expected database schema given your migrations files, and the actual schema of the database.
It should be understood as the set of changes to get from the expected schema to the actual schema.
[+] Added tables
- Post
- Profile
- User
[*] Changed the `Post` table
[+] Added foreign key on columns (authorId)
[*] Changed the `Profile` table
[+] Added foreign key on columns (userId)
- The following migration(s) are applied to the database but missing from the local migrations directory: 20211231005805_init
✔ We need to reset the MySQL database "mydb" at "db:3306".
Do you want to continue? All data will be lost. … yes
Applying migration `20211231010444_init`
The following migration(s) have been created and applied from new schema changes:
migrations/
└─ 20211231010444_init/
└─ migration.sql
Your database is now in sync with your schema.
✔ Generated Prisma Client (3.7.0 | library) to ./node_modules/@prisma/client in 282ms
4つの table が作成されていることを確認できました。
MySQL [mydb]> show tables;
+--------------------+
| Tables_in_mydb |
+--------------------+
| Post |
| Profile |
| User |
| _prisma_migrations |
+--------------------+
4 rows in set (0.005 sec)
migrate dev
の dev とは開発環境で実行するモードのようです。
migrate dev
は migration ファイルを作成した後にすぐに適用されます。
--create-only
を追加することで migration ファイルを作成するだけに留めることができます。
データを読み取る
DBにデータを追加します。
INSERT INTO `User` (`email`, `name`) VALUES ('hoge@example.com', 'hoge');
以下 index.ts を用意します。
import {PrismaClient} from '@prisma/client'
const prisma = new PrismaClient()
async function main() {
const allUsers = await prisma.user.findMany()
console.log(allUsers)
}
main()
.catch((e) => {
throw e
})
.finally(async () => {
await prisma.$disconnect()
})
以下のように読みとることができます。
$ npx ts-node src/index.ts
[ { id: 1, email: 'hoge@example.com', name: 'hoge' } ]
データの書き込み
先ほどの index.ts の main を書き換えて実行します。
async function main() {
await prisma.user.create({
data: {
name: 'Alice',
email: 'alice@prisma.io',
posts: {
create: { title: 'Hello World' },
},
profile: {
create: { bio: 'I like turtles' },
},
},
})
const allUsers = await prisma.user.findMany({
include: {
posts: true,
profile: true,
},
})
console.dir(allUsers, { depth: null })
}
$ npx ts-node src/index.ts
[
{
id: 1,
email: 'alice@prisma.io',
name: 'Alice',
posts: [
{
id: 1,
createdAt: 2021-12-31T08:29:02.391Z,
updatedAt: 2021-12-31T08:29:02.392Z,
title: 'Hello World',
content: null,
published: false,
authorId: 1
}
],
profile: { id: 1, bio: 'I like turtles', userId: 1 }
}
]
新規作成した user と紐付いた, post, profile が作成されていることがわかります。
client を更新する
model を更新した際、prisma generate
で更新します。
After you change your data model, you'll need to manually re-generate Prisma Client to ensure the code inside node_modules/.prisma/client gets updated: $ prisma generate
ここにわかりやすい更新のフローがあります。
試しに先ほどの model User に address カラムを追加し、prisma generate
を実行します。
npx prisma generate
Environment variables loaded from .env
Prisma schema loaded from prisma/schema.prisma
✔ Generated Prisma Client (3.7.0 | library) to ./node_modules/@prisma/client in 324ms
You can now start using Prisma Client in your code. Reference: https://pris.ly/d/client
import { PrismaClient } from '@prisma/client'
const prisma = new PrismaClient()
クライアントが更新されたので、エディタの complete で表示してくれるようになりました。
transaction
transaction も利用することができます
data load (seeding)
データのロード機能もあります。
Prisma モデルを利用した TypeScript ファイルを実行したり、shell で実行することができるようです。
試してみます。
prisma/seed.ts
を作成して以下のコードを貼り付けます。
import { PrismaClient } from '@prisma/client'
const prisma = new PrismaClient()
async function main() {
const alice = await prisma.user.upsert({
where: { email: 'alice@prisma.io' },
update: {},
create: {
email: 'alice@prisma.io',
name: 'Alice',
posts: {
create: {
title: 'Check out Prisma with Next.js',
content: 'https://www.prisma.io/nextjs',
published: true,
},
},
},
})
const bob = await prisma.user.upsert({
where: { email: 'bob@prisma.io' },
update: {},
create: {
email: 'bob@prisma.io',
name: 'Bob',
posts: {
create: [
{
title: 'Follow Prisma on Twitter',
content: 'https://twitter.com/prisma',
published: true,
},
{
title: 'Follow Nexus on Twitter',
content: 'https://twitter.com/nexusgql',
published: true,
},
],
},
},
})
console.log({ alice, bob })
}
main()
.catch((e) => {
console.error(e)
process.exit(1)
})
.finally(async () => {
await prisma.$disconnect()
})
package.json ファイルに seeding script をキックするための設定を追加します。
"prisma": {
"seed": "ts-node prisma/seed.ts"
},
npx prisma db seed
で seeding を実行します。
$ npx prisma db seed
Environment variables loaded from .env
Running seed command `ts-node prisma/seed.ts` ...
{
alice: { id: 1, email: 'alice@prisma.io', name: 'Alice' },
bob: { id: 2, email: 'bob@prisma.io', name: 'Bob' }
}
🌱 The seed command has been executed.
が芽生えてデータをロードすることができました。
触った感想
- model が型で補完をしてくれるので快適
- エラーメッセージが丁寧
- ドキュメントが丁寧
ORM は使い込まないと評価はできないと思うのですが、
少し触ってみた感想としてはとても良かったので続けて触ってみたいと思います。