Relational Mapping
Check this guide (opens in a new tab) to learn more about Prisma and ORM.
Database + Schema
Install the Prisma extension (opens in a new tab) for Visual Studio Code from the marketplace.
-
Create a Next.js application using
npx create-next-app@latest
.1 -
Install the Prisma package using
npm install --save-dev prisma
. -
Initialize Prisma with SQLite (opens in a new tab) as data source provider using
prisma init --datasource-provider sqlite --output ./client
.2 -
The environment variable
DATABASE_URL
in.env
can be updated with the desired location of the database file, for example,DATABASE_URL="file:data/dev.db"
. -
Update the schema,
prisma/schema.prisma
, with data models for a one-to-many relationship between users and their posts:- Each
User
has anid
entifier, a uniqueemail
, aname
, and a list ofposts
. - Each
Post
has anid
entifier, atitle
, a textcontent
, apublished
status, and a correspondingauthor
.
prisma/schema.prismamodel User { id String @id @default(cuid(2)) email String @unique name String? posts Post[] } model Post { id String @id @default(cuid(2)) title String content String? published Boolean @default(false) postAuthor User @relation(fields: [author], references: [id]) author String }
- Each
-
Create the supporting SQLite database using
prisma migrate dev --name init
. This will generate and execute a SQL migration3 against the database4 to define its tables and relationships. -
Use Prisma Studio,
prisma studio
, to view the database tables and edit/filter their records, if needed.
Client + Repository
-
Create a repository module,
repos/users.js
, to manage access to the data. -
Install5 the client library using
npm install @prisma/client
and use it to access the data in the repository:repos/users.jsimport { PrismaClient } from "@/prisma/client"; const prisma = new PrismaClient();
The client is custom-tailored to the data model and must be regenerated using
prisma generate
whenever the schema is updated6. -
Create a
disconnect()
method that closes a client connection, which will be used after having executed a query:repos/users.jsasync function disconnect() { try { await prisma.$disconnect(); } catch (e) { console.error(e); await prisma.$disconnect(); process.exit(1); } }
-
Create a
read()
method that returns all users along with their posts. It should calldisconnect()
after executing the queries and before returning the results. Useprisma.user.findMany()
and include the posts:repos/users.jsexport async function read() { const users = await prisma.user.findMany({ include: { posts: true, }, }); await disconnect(); return users; }
The generated SQL queries can be logged by setting the
log
option in thePrismaClient
constructor:new PrismaClient({ log: ["query"] })
. -
In a long-running application,
prisma.$disconnect()
should not be explicitly called. One approach is to avoid callingdisconnect()
and instead create a client module,repos/prisma.js
, then import it inrepos/users.js
to cache thePrismaClient
instance and reuse it across the application:repos/prisma.jsimport { PrismaClient } from "@/prisma/client"; const prisma = new PrismaClient(); export default prisma;
repos/users.jsimport prisma from "@/repos/prisma";
RESTful API
-
Import and use the repository in
api/users/route.js
to implement aGET
method that returns all users along with their posts usingread()
:app/api/users/route.jsimport * as users from "@/repos/users.js"; export async function GET(request) { return Response.json(await users.read()); }
-
Test the route using Postman (opens in a new tab).
Seeding
-
Create a
prisma/seed.mjs
script that uses the Faker (opens in a new tab) package7 to procedurally generate sample data and populates the database usingprisma.user.create()
:prisma/seed.mjsimport { PrismaClient } from "./client/index.js"; import { faker } from "@faker-js/faker"; const prisma = new PrismaClient(); const seed = async () => { Array.from({ length: Math.floor(Math.random() * 60) }).forEach( async () => await prisma.user.create({ data: { email: faker.internet.email(), name: faker.person.fullName(), posts: { create: Array.from({ length: Math.floor(Math.random() * 12), }).map(() => ({ title: faker.commerce.productName(), content: faker.lorem.text(), published: Math.random() > 0.5, })), }, }, }), ); }; try { await seed(); await prisma.$disconnect(); } catch (e) { console.error(e); await prisma.$disconnect(); process.exit(1); }
-
Add the following lines at the top level of
package.json
to automatically seed the database inprisma migrate dev
andprisma migrate reset
. The script can also be manually invoked usingprisma db seed
:package.json{ ••• "prisma": { "seed": "node prisma/seed.mjs" } }
Footnotes
-
This guide is based on the Prisma Get Started / Quickstart (opens in a new tab) guide. ↩
-
Use
npx prisma [command]
for all Prisma commands. ↩ -
prisma db push
can be used instead if migrations are not needed. ↩ -
prisma db pull
can be used instead with a pre-existing database. ↩ -
prisma migrate
already performs this step. ↩ -
Install Prisma DBML Generator (opens in a new tab) to automatically generate DBML (opens in a new tab) diagrams. ↩
-
Install the Faker package using
npm install --save-dev @faker-js/faker
. ↩