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_URLin.envcan 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
Userhas anidentifier, a uniqueemail, aname, and a list ofposts. - Each
Posthas anidentifier, atitle, a textcontent, apublishedstatus, 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/clientand 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 generatewhenever 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
logoption in thePrismaClientconstructor: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.jsto cache thePrismaClientinstance 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.jsto implement aGETmethod 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.mjsscript 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.jsonto automatically seed the database inprisma migrate devandprisma 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 pushcan be used instead if migrations are not needed. ↩ -
prisma db pullcan be used instead with a pre-existing database. ↩ -
prisma migratealready 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. ↩