Module 61: Database Integration

Lesson 3 of 5 · 15–25 minutes

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

npm install prisma --save-dev
npm install @prisma/client
npx prisma init
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.

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 */ });

🖱️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.

← PreviousWhat an ORM is
ProLearners Assist