Bài 7. Kết nối cơ sở dữ liệu với Prisma và MySQL

Prisma là ORM phổ biến nhất cho TypeScript: mô tả bảng bằng schema, sinh mã truy vấn có kiểu, quản lý migration. Bài này kết nối Next.js với MySQL (CSDL qlsv từ loạt SQL), định nghĩa model, quan hệ và viết truy vấn CRUD, phân trang.

60 phútNâng cao
Bạn sẽ học được
  • Cài Prisma, cấu hình MySQL
  • Viết schema, quan hệ, chạy migration
  • Truy vấn CRUD, lọc, phân trang, include
  • Dùng Prisma an toàn trong Next.js

Một số khái niệm

  • ORM: làm việc với bảng như đối tượng, không phải viết SQL bằng tay (vẫn dùng được SQL thô khi cần).
  • schema.prisma: mô tả model, kiểu, quan hệ.
  • Migration: tệp SQL ghi lại thay đổi cấu trúc CSDL theo thời gian.
  • Prisma Client: mã truy vấn được sinh ra có gợi ý và kiểm tra kiểu.

Cài đặt

npm install prisma -D
npm install @prisma/client
npx prisma init --datasource-provider mysql
# .env
DATABASE_URL="mysql://root:@localhost:3306/qlsv"

Schema

// prisma/schema.prisma
model Lop {
  id       Int        @id @default(autoincrement())
  ma_lop   String     @unique @db.VarChar(20)
  ten_lop  String     @db.VarChar(100)
  sinhVien SinhVien[]
  @@map("lop")
}

model SinhVien {
  id        Int      @id @default(autoincrement())
  ma_sv     String   @unique @db.Char(8)
  ho_ten    String   @db.VarChar(100)
  email     String?  @db.VarChar(100)
  lop       Lop?     @relation(fields: [lop_id], references: [id])
  lop_id    Int?
  createdAt DateTime @default(now())
  @@map("sinh_vien")
}
npx prisma migrate dev --name khoi-tao   # tạo bảng
# hoặc lấy cấu trúc từ CSDL có sẵn:
npx prisma db pull && npx prisma generate
npx prisma studio                         # giao diện xem dữ liệu

Truy vấn

// src/lib/db.ts — một thể hiện duy nhất (tránh tạo nhiều kết nối khi dev)
import 'server-only';
import { PrismaClient } from '@prisma/client';
const g = globalThis as unknown as { prisma?: PrismaClient };
export const db = g.prisma ?? new PrismaClient();
if (process.env.NODE_ENV !== 'production') g.prisma = db;
const trang = 2, kichThuoc = 10;
const [ds, tong] = await Promise.all([
  db.sinhVien.findMany({
    where: { ho_ten: { contains: 'An' }, lop: { ma_lop: 'K66CNTT' } },
    include: { lop: true },
    orderBy: { ho_ten: 'asc' },
    skip: (trang - 1) * kichThuoc, take: kichThuoc,
  }),
  db.sinhVien.count(),
]);
await db.sinhVien.update({ where: { id: 5 }, data: { email: Địa chỉ email này đang được bảo vệ từ spam bots, bạn cần kích hoạt Javascript để xem nó. Bạn cần kích hoạt Javascript để xem nó.' } });
await db.sinhVien.delete({ where: { id: 5 } });
const thongKe = await db.sinhVien.groupBy({ by: ['lop_id'], _count: true });
Mẹo hay

Drizzle ORM là lựa chọn nhẹ hơn, cú pháp gần SQL; MySQL có thể thay bằng PostgreSQL (Supabase, Neon) khi triển khai lên đám mây mà không đổi mã truy vấn.

Lưu ý

Chỉ import Prisma trong mã máy chủ (Server Component, Server Action, Route Handler). Nếu lỡ import vào Client Component, gói server-only sẽ báo lỗi ngay khi build.

Thực hành
  1. Kết nối Prisma với CSDL qlsv bằng db pull.
  2. Trang danh sách sinh viên có tìm kiếm, phân trang.
  3. Trang chi tiết lớp kèm danh sách sinh viên (include).
  4. Hoàn thiện CRUD bằng Server Actions dùng Prisma.
Tóm tắt bài học
  • schema.prisma mô tả model và quan hệ.
  • migrate dev hoặc db pull + generate.
  • findMany, create, update, delete, include, groupBy.
  • Dùng một PrismaClient, chỉ ở phía máy chủ.