Week 11: Prisma!
Source: Dev.to
Topics Covered✅
- Understanding what an ORM actually solves
- Defining a database schema using Prisma
- Generating type‑safe database clients
- Performing CRUD operations cleanly and safely
1. What is Prisma and why do we need it? 🧠
Prisma is an ORM (Object Relational Mapper) that acts as a bridge between your database and application code.
Without Prisma
SELECT * FROM users WHERE email = 'test@gmail.com';
With Prisma
const user = await prisma.user.findUnique({
where: { email: "test@gmail.com" }
});
Why this matters
- No need to write raw SQL for every operation
- Queries become type‑safe
- Refactoring database fields doesn’t silently break things
- Autocomplete + compile‑time checks prevent runtime bugs
2. Prisma Schema — the single source of truth 📄
First, initialise Prisma in your project (see the official docs).
The schema.prisma file defines:
- Database connection
- Models (tables)
- Relationships between models
Basic example
model User {
id Int @id @default(autoincrement())
email String @unique
name String?
createdAt DateTime @default(now())
}
- Creates a
Usertable - Enforces uniqueness on
email - Generates types that your editor understands
Generate the client:
npx prisma generate
Using the generated client
import { PrismaPg } from '@prisma/adapter-pg';
import { PrismaClient } from "@/app/generated/prisma/client";
const adapter = new PrismaPg({
connectionString: process.env.DATABASE_URL,
});
const prisma = new PrismaClient({ adapter });
3. Migrations — evolving the database safely 🔁
Databases change over time. Prisma handles schema changes through migrations.
npx prisma migrate dev --name add-user-model
What this does:
- Creates a migration file
- Applies changes to the database
- Keeps a history of schema evolution
Migrations keep your local, staging, and production databases in sync, and the generated files contain the raw SQL for each change.
4. CRUD operations with Prisma ✍️
Create
await prisma.user.create({
data: {
email: "nikhil@gmail.com",
name: "Nikhil"
}
});
Read
const users = await prisma.user.findMany();
Update
await prisma.user.update({
where: { id: 1 },
data: { name: "Updated Name" }
});
Delete
await prisma.user.delete({
where: { id: 1 }
});
All operations are:
- Typed
- Validated at compile time
- Predictable in behaviour
Refer to the Prisma docs for full parameter details.
5. Relations and foreign keys made simple 🔗
Defining relations in Prisma is clean and expressive.
model User {
id Int @id @default(autoincrement())
posts Post[]
}
model Post {
id Int @id @default(autoincrement())
title String
user User @relation(fields: [userId], references: [id])
userId Int
}
Prisma now understands:
- One user → many posts
- How to join data internally
- How to fetch nested data safely
Fetching related data
const user = await prisma.user.findUnique({
where: { id: 1 },
include: { posts: true }
});
6. New things I learned this week 🔄
- Prisma acts as an intermediary between code and database, providing type safety that dramatically reduces bugs.
- A schema‑first design prevents an entire class of runtime errors.
Wrapping up
Prisma may feel like “just another tool,” but it fundamentally changes how confidently we interact with databases. Clean schemas and safe migrations make production systems far more reliable.
If you have any questions or feedback, feel free to comment! And if you have project ideas for me, drop them in the comments.
I’ll be back next week with more. Until then, stay consistent!