この記事ではNext.jsでPrismaを使う方法をご紹介します。
Prismaを使うことでJSでデータベース作ったり、クエリを発行してデータを取得することができてとても便利です。
この記事ではPlatforms Starter KitとPrisma Examplesを参考にしています。
prisma.jsとは
Node.js 製の ORMです。
prisma.jsを使うことで、データベースをjsで作ることができたり、ORMなのでjsでクエリを発行できたりします。
- PostgreSQL
- MySQL
- SQL Server
- SQLite
- MongoDB
- CockroachDB
に対応しています。
Next.jsをインストール
はじめにNext.jsをサクッとインストールします。もちろんtypescriptで。
Prismaもtypescriptに対応しています。
$ yarn create next-app --typescript
yarn create v1.22.10
[1/4] 🔍 Resolving packages...
[2/4] 🚚 Fetching packages...
[3/4] 🔗 Linking dependencies...
[4/4] 🔨 Building fresh packages...
success Installed "create-next-app@12.1.6" with binaries:
- create-next-app
✔ What is your project named? …
...
✨ Done in 30.27s.
Next.jsの開発に不安がある方はこちらの書籍がおすすめです。
初心者〜中級者向きで、基礎から話題のライブラリを活用した開発も学べます。
Prismaを設定
インストール
Prismaを利用するためには次の2つが必要になるので、これらをインストールします。
- @prisma/client
- prisma
$ yarn add @prisma/client
yarn add v1.22.10
[1/4] 🔍 Resolving packages...
[2/4] 🚚 Fetching packages...
...
info All dependencies
├─ @prisma/client@3.14.0
└─ @prisma/engines-version@3.14.0-36.2b0c12756921c891fec4f68d9444e18c7d5d4a6a
✨ Done in 21.16s.
$ yarn add prisma --dev
yarn add v1.22.10
[1/4] 🔍 Resolving packages...
[2/4] 🚚 Fetching packages...
...
info All dependencies
├─ @prisma/engines@3.14.0-36.2b0c12756921c891fec4f68d9444e18c7d5d4a6a
└─ prisma@3.14.0
✨ Done in 11.83s.
スキーマを設定
まずは次のコマンドを実行してprismaでデータベーススキーマを設定するフォルダを生成します。
$ npx prisma init
prisma/schema.prismaが生成されました。
このファイルに次のようにスキーマを設定します。
今回のデータベースはSqliteにしました。mysqlなど他のデータベースにも対応しています。
Prisma VS Code Extensionを入れておくとハイライトしてくれます。
// datasource db {
// provider = "mysql"
// url = env("DATABASE_URL")
// referentialIntegrity = "prisma"
// }
datasource db {
provider = "sqlite"
url = env("DATABASE_URL")
referentialIntegrity = "prisma"
}
generator client {
provider = "prisma-client-js"
previewFeatures = ["referentialIntegrity"]
}
model User {
id String @id @default(cuid())
name String?
// if you are using Github OAuth, you can get rid of the username attribute (that is for Twitter OAuth)
username String?
gh_username String?
email String? @unique
emailVerified DateTime?
image String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
sessions Session[]
}
model Session {
id String @id @default(cuid())
sessionToken String @unique
userId String
expires DateTime
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
@@index([userId])
}
model VerificationToken {
identifier String
token String @unique
expires DateTime
@@unique([identifier, token])
}
環境変数でデータベースのURLを設定します。
# MySQL database URL for Prisma
DATABASE_URL=file:./dev.db
データベース作成
prismaで設定したデータベースのスキーマを実行してデータベースを作ります。
$ npx prisma migrate dev --name init
Environment variables loaded from .env
Prisma schema loaded from prisma/schema.prisma
Datasource "db": SQLite database "dev.db" at "file:./dev.db"
...
migrations/
└─ 20220513034656_init/
└─ migration.sql
Your database is now in sync with your schema.
✔ Generated Prisma Client (3.14.0 | library) to ./node_modules/@p
risma/client in 1.29s
Sqliteでデータベースを作成したので、prisma/deb.dbが作成されます。
schema.prisma
を新規作成や編集したら、prisma generate
で prisma client への反映をする必要があります。。
$ prisma generate
Environment variables loaded from .env
Prisma schema loaded from prisma/schema.prisma
✔ Generated Prisma Client (3.14.0 | library) to ./node_modules/@prisma/client in 137ms
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()
```
✨ Done in 4.42s.
npm scriptsにprisma generate
を設定しておくと便利です。
{
...
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint",
"prebuild": "prisma generate", // 追加
"predev": "prisma generate", // 追加
"prisma:migrate": "prisma migrate deploy" // 追加
},
...
}
発行クエリをログで表示する
libディレクトリとprisma.tsを新規作成して、次のコードを設定します。
import { PrismaClient } from "@prisma/client";
declare global {
var prisma: PrismaClient | undefined;
}
const prisma =
global.prisma ||
new PrismaClient({
log: ["query", "error", "info", "warn"],
});
if (process.env.NODE_ENV === "development") global.prisma = prisma;
export default prisma;
https://www.prisma.io/docs/concepts/components/prisma-client/working-with-prismaclient/logging
発行したクエリがログで表示されるか確認してみます。
pages/index.tsxでGetServerSideProps
を使用してユーザー数を取得します。
import type { NextPage, GetServerSideProps } from "next";
import Head from "next/head";
import Image from "next/image";
import styles from "../styles/Home.module.css";
import prisma from "../lib/prisma";
const Home: NextPage = () => {
return (
<div className={styles.container}>
...
</div>
);
};
export const getServerSideProps: GetServerSideProps<{
count: number;
}> = async (ctx) => {
const count = await prisma.user.count();
return {
props: {
count,
},
};
};
export default Home;
prisma.user.count()
で発行されたクエリがログで以下のように表示されました。
prisma:info Starting a sqlite pool with 9 connections.
prisma:query SELECT COUNT(*) FROM (SELECT `main`.`User`.`id` FROM `main`.`User` WHERE 1=1 LIMIT ? OFFSET ?) AS `sub`
Prismaを使ったデータ取得方法
ここでは簡単にPrismaを使ったデータの取得方法をご紹介します。
Prismaを使ったCRUDの記述例はこちらで確認できます。
クエリの使い方
id
が1のユーザーのname
とprofileViews
のみ取得する
const result = await prisma.user.findUnique({
where: { id: 1 },
select: {
name: true,
profileViews: true,
},
})
ユーザーのemail
とrole
のみ複数取得する
const result = await prisma.user.findMany({
select: {
email: true,
role: true,
},
})
ユーザーの投稿数をカウントしてユーザーを複数取得する
const usersWithCount = await prisma.user.findMany({
select: {
_count: {
select: { posts: true },
},
},
})
ユーザーとそのユーザーの投稿のid
とtitle
のみを取得する
const result = await prisma.user.findMany({
select: {
id: true,
name: true,
posts: {
select: {
id: true,
title: true,
},
},
},
})
select
の中にinclude
をすることもできます。
const result = await prisma.user.findMany({
select: {
id: true,
name: true,
posts: {
include: {
author: true,
},
},
},
})
コメント