Module 61: Database Integration
Prisma in practice
🏠The everyday picture
A building plan from which the builder, the electrician and the inspector all work. Change the plan, and everyone's work updates from it.
📘What it really is
- Set up:
npm install prisma --save-dev
npm install @prisma/client
npx prisma init
- Describe tables in
prisma/schema.prisma:
model Customer {
id String @id @default(uuid()) @db.Uuid
name String
email String? @unique
phone String
city String
createdAt DateTime @default(now()) @map("created_at") @db.Timestamptz
orders Order[]
@@map("customers")
}
model Order {
id String @id @default(uuid()) @db.Uuid
customer Customer @relation(fields: [customerId], references: [id], onDelete: Restrict)
customerId String @map("customer_id") @db.Uuid
totalPaise Int @map("total_paise")
placedAt DateTime @map("placed_at") @db.Timestamptz
@@index([customerId])
@@map("orders")
}
@map keeps snake_case names in the database and camelCase in code.
-
npx prisma migrate dev --name initcreates and runs a migration (SQL you can read inprisma/migrations/).npx prisma migrate deployapplies migrations in production. -
Queries:
await prisma.customer.create({ data: { name, phone, city } });
await prisma.customer.findMany({ where: { city: "Patna" }, orderBy: { name: "asc" }, take: 25 });
await prisma.order.findMany({ include: { customer: true } }); // join, not N+1
await prisma.$transaction(async (tx) => { /* several operations */ });
-
For SQL Prisma can't express well, use
prisma.$queryRawwith its tagged template, which still parameterises:prisma.$queryRaw`SELECT ... WHERE city = ${city}`. Never use theUnsafevariants with user input. -
npx prisma studioopens a browser view of your data. - If you already have a database,
npx prisma db pullcreates the schema from it.
🖱️Try it
Add Prisma to your API. Use prisma db pull on your Module 60 database (or write the schema), then reimplement one
repository with Prisma. Turn on query logging (new PrismaClient({ log: ["query"] })) and check that loading orders with
customers uses a join or a single extra query, not one per order.
✅Quick check
What does @map("created_at") do?
Show the answer
Uses created_at as the column name in the database while the code uses createdAt.
Is prisma.$queryRaw`... ${city}` safe from SQL injection?
Show the answer
Yes: the tagged template sends city as a parameter. The Unsafe variants aren't safe with user input.
