Next.jsでPrismaを使ってデータベースを作る

この記事ではNext.jsでPrismaを使う方法をご紹介します。

Prismaを使うことでJSでデータベース作ったり、クエリを発行してデータを取得することができてとても便利です。

この記事ではPlatforms Starter KitPrisma Examplesを参考にしています。

目次

prisma.jsとは

 Node.js 製の ORMです。

prisma.jsを使うことで、データベースをjsで作ることができたり、ORMなのでjsでクエリを発行できたりします。

https://www.prisma.io/docs/getting-started/setup-prisma/start-from-scratch/relational-databases-typescript-postgres

  • 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のユーザーのnameprofileViewsのみ取得する

const result = await prisma.user.findUnique({
  where: { id: 1 },
  select: {
    name: true,
    profileViews: true,
  },
})

ユーザーのemailroleのみ複数取得する

const result = await prisma.user.findMany({
  select: {
    email: true,
    role: true,
  },
})

ユーザーの投稿数をカウントしてユーザーを複数取得する

const usersWithCount = await prisma.user.findMany({
  select: {
    _count: {
      select: { posts: true },
    },
  },
})

ユーザーとそのユーザーの投稿のidtitleのみを取得する

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,
      },
    },
  },
})
よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

コメント

コメントする


reCaptcha の認証期間が終了しました。ページを再読み込みしてください。

目次