6.12-bob: ORM — Prisma (schema, migrate, client, relations)
6-QISM — Ma'lumotlar bazasi (Database) · 12-mavzu
1. Kirish va motivatsiya
Sequelize (klassik ORM — 6.11) ni bildik. Endi zamonaviy, type-safe (tur-xavfsiz) ORM — Prisma ga o'tamiz. Prisma — bugungi kunda yangi loyihalar uchun eng ko'p tavsiya etiladigan ORM (ayniqsa TypeScript bilan). Sababi: u boshqacha, deklarativ yondashuvni qo'llaydi — bitta schema.prisma faylda butun ma'lumot modelini ta'riflaysiz, Prisma esa undan avtomatik type-safe client generatsiya qiladi. Bu — ajoyib developer experience (avtomat to'ldirish, tur tekshiruvi, xatolarni kompilyatsiyada ushlash).
Sequelize'da modellarni JS kodida (define) yozdik. Prisma'da — alohida schema fayl (schema.prisma) — barcha modellar, bog'lanishlar, sozlamalar bir joyda, o'qiladigan. Keyin prisma generate — schema'dan Prisma Client (tur bilan) yaratadi. prisma migrate — schema'ni DB'ga qo'llaydi (migration avtomatik). Bu — schema yagona haqiqat manbai (single source of truth): schema o'zgarsa, client va DB ham (sinxron).
Prisma'ning eng kuchli tomoni — type-safety: TypeScript (7) bilan har so'rov, natija, maydon tur bilan (autocompletion, xato kompilyatsiyada). user.emial (typo) — Prisma'da kompilyatsiya xatosi (Sequelize'da runtime'da bilinadi). 2025-yil oxirida Prisma 7 chiqdi — to'liq TypeScript runtime (3x tezroq). Bu bob: schema, migrate, client, relations, va type-safe so'rovlar — chuqur.
O'xshatish: Sequelize — qo'lda yasalgan mebel (har bo'lakni o'zingiz kesasiz/yig'asiz — moslashuvchan, lekin ko'p ish). Prisma — IKEA to'plami: chizma (schema.prisma) bo'yicha tayyor, aniq bo'laklar (generatsiya qilingan client) — tez yig'asiz, hammasi mos keladi (type-safe), xato kam. Chizmani o'zgartirsangiz, bo'laklar ham (migrate). Zamonaviy, ishonchli.
Nega muhim?
- Zamonaviy tanlov — yangi loyiha (ayniqsa TS) uchun eng ko'p tavsiya.
- Type-safety — xatolarni kompilyatsiyada ushlash (runtime'da emas).
- DX — schema, avtomat client, autocompletion — tez, kam xato.
- Stack talabi — Prisma sizning stack'ingda; NestJS, Next.js bilan a'lo.
2. Nazariya — chuqur tushuntirish
2.1. Prisma nima va arxitekturasi
Prisma — zamonaviy, type-safe ORM (prisma.io). Uch qismdan iborat:
1. Prisma Schema (schema.prisma) — ma'lumot modeli (yagona manba)
2. Prisma Client — schema'dan AVTOMATIK generatsiya (type-safe so'rovlar)
3. Prisma Migrate — schema'ni DB'ga qo'llash (migration)
Oqim:
schema.prisma yozing prisma generate (client) prisma migrate (DB) kodda ishlatingAsosiy farq (Sequelize'dan): Sequelize'da model — JS kod. Prisma'da — deklarativ schema fayl + avtomatik client. Schema — yagona haqiqat (single source of truth): undan ham client, ham DB hosil bo'ladi (sinxron).
2.2. Type-safety (eng kuchli tomon)
Sequelize (tur yo'q to'liq):
const user = await User.findByPk(1);
user.emial // typo RUNTIME'da undefined (xato keyin bilinadi)
Prisma (type-safe — TS):
const user = await prisma.user.findUnique({ where: { id: 1 } });
user.emial // KOMPILYATSIYA xatosi (darrov bilinadi — TS — 7)
user.email // autocompletion, tur bilanType-safety qiymati (talent500): Prisma TypeScript (7) bilan har narsani tipladi — model, so'rov, natija, maydon. Xato kompilyatsiyada (runtime'da emas — ishlatishdan oldin). Bu — ishonchlilik va tezlikni keskin oshiradi (autocompletion, refactoring xavfsiz).
2.3. O'rnatish va init
npm install prisma --save-dev # CLI
npm install @prisma/client # client
npx prisma init # schema.prisma + .env yaratadi Hosil bo'ladi:
prisma/schema.prisma — schema fayl 2.4-bob
.env — DATABASE_URL (5.8)2.4. Prisma Schema (schema.prisma)
Schema — butun ma'lumot modeli bir faylda (prisma.io):
// prisma/schema.prisma
generator client {
provider = "prisma-client-js" // client generatsiyasi
}
datasource db {
provider = "postgresql" // DB turi (mysql, sqlite, mongodb ham)
url = env("DATABASE_URL") // .env (5.8)
}
model User {
id Int @id @default(autoincrement()) // PK, avto (6.4)
ism String
email String @unique // noyob (6.4)
yosh Int? // ? — ixtiyoriy (nullable)
rol Role @default(USER) // enum (2.5)
orders Order[] // bog'lanish (one-to-many — 2.6)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt // avtomatik (6.2)
}
enum Role { USER ADMIN } // enumSchema sintaksisi:
model(jadval), maydon: nom + tur + atributlar (@id,@unique,@default,@updatedAt).?— nullable (ixtiyoriy).Int?(NULL bo'lishi mumkin),Int(majburiy).Order[]— bog'lanish (massiv). Toza, o'qiladigan, bir joyda.
2.5. Maydon turlari va atributlar
model Product {
id Int @id @default(autoincrement())
nom String @db.VarChar(100) // DB tur (VARCHAR(100))
narx Decimal @db.Decimal(10, 2) // DECIMAL (pul — 6.4: 2.3)
tavsif String? @db.Text // ixtiyoriy, uzun
faol Boolean @default(true)
xususiyat Json? // JSONB (6.6: 2.10)
teglar String[] // massiv (PostgreSQL — 6.6: 2.13)
slug String @unique
@@index([nom]) // indeks (6.10)
@@map("products") // jadval nomi
}Atributlar: maydon (
@) —@id,@unique,@default,@db.X(aniq DB tur). Model (@@) —@@index,@@unique,@@map(jadval nomi).Decimal(pul),Json(JSONB),String[](massiv) — DB imkoniyatlari schema'da.
2.6. Relations (bog'lanishlar)
// One-to-Many: User ko'p Order
model User {
id Int @id @default(autoincrement())
orders Order[] // bir user — ko'p order
}
model Order {
id Int @id @default(autoincrement())
user User @relation(fields: [userId], references: [id]) // bog'lanish (FK)
userId Int // FK ustun
summa Decimal @db.Decimal(10, 2)
}// Many-to-Many (Prisma avtomatik junction jadval yaratadi)
model Post { id Int @id @default(autoincrement()); tags Tag[] }
model Tag { id Int @id @default(autoincrement()); posts Post[] }
@relation— bog'lanishni belgilaydi (FK —fields/references— 6.1: 2.5). One-to-many: bir tomonda massiv (Order[]), boshqasida obyekt + FK (user/userId). Many-to-many — ikki tomonda massiv; Prisma junction jadvalni avtomatik yaratadi (Sequelize'da qo'lda — 6.11: 2.8).
2.7. Migrate (schema DB)
Prisma Migrate — schema o'zgarishini DB'ga qo'llaydi (avtomatik migration — prisma.io):
npx prisma migrate dev --name init # dev: migration yaratadi + qo'llaydi
npx prisma migrate deploy # production: mavjud migration'larni qo'llaydi
npx prisma migrate reset # DB'ni tozalab, qayta (dev — ehtiyot!)Sequelize'dan farq: Sequelize'da migration qo'lda yozasiz (6.11: 2.11). Prisma — schema'ni o'zgartirasiz,
migrate devavtomatik SQL migration yaratadi (farqni hisoblab). Migration fayllar (prisma/migrations/) — git'da (4). Production'damigrate deploy.
2.8. Generate (client yaratish)
npx prisma generate # schema'dan Prisma Client generatsiya schema.prisma prisma generate @prisma/client (type-safe)
Schema O'ZGARSA qayta generate (client yangilanadi — type bilan)
migrate dev avtomatik generate ham qiladi
prisma generate— schema'dan TypeScript client (tur bilan) yaratadi. Schema o'zgarsa — qayta generate (yangi turlar). Bu — type-safety'ning manbai 2.2-bob: client schema'ga aniq mos (autocompletion).
2.9. Prisma Client — CRUD
import { PrismaClient } from "@prisma/client";
const prisma = new PrismaClient(); // client (2.10: bir marta)
// CREATE
await prisma.user.create({ data: { ism: "Ali", email: "ali@a.uz" } });
// READ
await prisma.user.findMany(); // hammasi
await prisma.user.findUnique({ where: { id: 1 } }); // PK/unique
await prisma.user.findFirst({ where: { rol: "ADMIN" } });
await prisma.user.findMany({ where: { yosh: { gt: 18 } } }); // operator (2.11)
// UPDATE
await prisma.user.update({ where: { id: 1 }, data: { yosh: 26 } });
// DELETE
await prisma.user.delete({ where: { id: 1 } });Prisma so'rovlari — obyekt asosli (
where,data,include,select).findUnique(PK/unique),findFirst(bitta shartli),findMany(ko'p). Hammasi type-safe (model maydonlari autocompletion).
2.10. PrismaClient — bir marta (singleton)
PrismaClient — bir marta yaratiladi (ko'p instance — ulanish tugaydi):
// lib/prisma.js — singleton (2.10)
import { PrismaClient } from "@prisma/client";
const globalForPrisma = globalThis;
export const prisma = globalForPrisma.prisma || new PrismaClient();
if (process.env.NODE_ENV !== "production") globalForPrisma.prisma = prisma;
// Dev'da hot-reload har safar yangi client yaratmasligi uchun (Next.js — 13)PrismaClient singleton: har so'rovda/faylda yangi
PrismaClient()— ko'p ulanish DB ulanishlari tugaydi. Bir marta yarating, import qiling (6.5: pool kabi). Dev'da (hot-reload — Next.js)globalThisbilan saqlash (manba).
Nega singleton muhim? Chunki har bir PrismaClient o'z ulanish hovuzini (connection pool — 6.5) ochadi. Prisma ulanishlarni qayta ishlatadi (har so'rovga yangi ulanish emas — bu 6.5'dagi pool g'oyasi):
PrismaClient (1 dona)
└── ulanish hovuzi (pool) — bir nechta tayyor ulanish
so'rov hovuzdan ulanish olinadi ishlatiladi hovuzga qaytariladi
Ko'p PrismaClient ko'p hovuz DB ulanish limiti tugaydi (xato)Hovuz o'lchamini DATABASE_URL da sozlash mumkin:
postgresql://user:pass@host:5432/db?connection_limit=10Connection pool 6.5-bob: bitta
PrismaClient— bitta hovuz (default o'lcham:num_cpu * 2 + 1). Serverless (Vercel, Lambda) da har funksiya alohida hovuz ochadi — DB limiti tez tugaydi; shuning uchun Prisma Accelerate yokipgbouncer(tashqi pooler) ishlatiladi. Odatiy serverda singleton 2.10-bob yetarli.connection_limit— hovuzdagi maksimal ulanish.
2.11. So'rov operatorlari va filtrlash
await prisma.product.findMany({
where: {
narx: { gte: 1000, lte: 5000 }, // oraliq (>=, <=)
kategoriya: { in: ["telefon", "kompyuter"] }, // IN
nom: { contains: "phone", mode: "insensitive" }, // LIKE (matn qidiruv)
OR: [{ faol: true }, { zaxira: { gt: 0 } }], // OR
},
orderBy: { narx: "desc" }, // ORDER BY (6.4)
take: 10, skip: 20, // limit, offset (sahifalash)
select: { id: true, nom: true, narx: true }, // SELECT ustunlar
});Operatorlar:
gt/gte/lt/lte(taqqoslash),in/notIn,contains/startsWith(matn),AND/OR/NOT.take/skip(limit/offset — 6.4: 2.10),orderBy,select(ustunlar). MongoDB 6.2-bob va Sequelize Op 6.11-bob ga o'xshash, lekin type-safe.
2.12. Relations bilan ishlash (include / select)
Include — bog'langan ma'lumotni birga olish (JOIN — eager — prisma.io):
// User + buyurtmalari (include — JOIN)
const user = await prisma.user.findUnique({
where: { id: 1 },
include: { orders: true }, // buyurtmalarni ham (type-safe)
});
console.log(user.orders); // tur bilan!
// Nested include + shart + select
await prisma.user.findMany({
include: {
orders: {
where: { holat: "tugallandi" }, // shartli
include: { items: { include: { product: true } } }, // ichma-ich
},
},
});
include(eager — N+1 oldini oladi — 2.16) — bog'langan ma'lumotni type-safe olib keladi (natija to'g'ri tiplangan — manba).select— faqat kerakli maydonlar. Nested — ichma-ich (user order item product). Sequelize include'iga o'xshash, lekin tur bilan.
2.13. Nested write (bog'liq ma'lumotni birga yozish)
Prisma bitta so'rovda bog'liq ma'lumot yaratadi (nested write — tranzaksiya — prisma.io):
// User + uning buyurtmasi BIRGA (bitta tranzaksiyada)
await prisma.user.create({
data: {
ism: "Ali", email: "ali@a.uz",
orders: { // bog'liq order birga (nested)
create: [{ summa: 50000 }, { summa: 30000 }], // ikkita order
},
},
include: { orders: true },
});
// User + 2 order BITTA tranzaksiyada (biri xato bo'lsa — hammasi rollback — 2.14)Nested write — bog'liq ma'lumotni bir so'rovda, atomik (prisma.io).
create,connect(mavjudga ulash),connectOrCreate,update. Bu — tranzaksiya kafolati 2.14-bob bilan. Sequelize'da ko'p qadam kerak edi; Prisma — bir so'rov.
2.14. Tranzaksiya
// 1. Nested write — avtomatik tranzaksiya (2.13)
// 2. Bulk amallar (createMany/updateMany/deleteMany) — avtomatik tranzaksiya
// 3. Interactive transaction (murakkab mantiq — 6.9)
await prisma.$transaction(async (tx) => {
const from = await tx.account.update({ where: { id: 1 }, data: { balans: { decrement: 100 } } });
if (from.balans < 0) throw new Error("Balans yetarli emas"); // rollback
await tx.account.update({ where: { id: 2 }, data: { balans: { increment: 100 } } });
});
// xato bo'lsa — avtomatik ROLLBACK (6.9: ACID)
// 4. Sequential transaction (mustaqil amallar)
await prisma.$transaction([
prisma.user.create({ ... }),
prisma.order.create({ ... }),
]);Prisma tranzaksiya — 4 usul: nested write 2.13-bob, bulk (avtomatik),
$transaction(async tx)(interactive — murakkab mantiq, 6.9),$transaction([...])(massiv — mustaqil).increment/decrement— atomik (6.9: 2.11). Xato avtomatik rollback.
2.15. Prisma Studio (vizual DB)
npx prisma studio # brauzerda DB'ni ko'rish/tahrirlash (GUI)Prisma Studio — DB'ni brauzerda ko'rish/tahrirlash (admin panel kabi). Dev'da juda qulay (ma'lumotni ko'rish, test). Prisma'ning DX afzalliklaridan.
2.16. N+1 va performance
N+1 (tsiklda alohida — 6.10: 2.11):
const users = await prisma.user.findMany();
for (const u of users) await prisma.order.findMany({ where: { userId: u.id } });
include (bir so'rov — 2.12):
await prisma.user.findMany({ include: { orders: true } });Prisma N+1'ni
includebilan oldini oladi 2.12-bob. Prisma so'rov logini ko'rsatish:new PrismaClient({ log: ["query"] })— generatsiya SQL'ni ko'rish (2.14, 6.10). Murakkab so'rov uchun$queryRaw(xom SQL, type-safe parametr).
2.17. Prisma vs Sequelize vs TypeORM (taqqoslash)
┌──────────────┬──────────────┬──────────────┬──────────────┐
│ │ Prisma │ Sequelize │ TypeORM │
├──────────────┼──────────────┼──────────────┼──────────────┤
│ Yondashuv │ schema fayl │ JS model │ class+dekor. │
│ Type-safety │ a'lo │ ~ │ yaxshi │
│ DX │ a'lo │ o'rtacha │ yaxshi │
│ Migration │ avtomatik │ qo'lda │ avtomatik │
│ NestJS │ yaxshi │ ~ │ tabiiy │
│ Murakkab SQL │ raw │ raw │ query builder│
└──────────────┴──────────────┴──────────────┴──────────────┘Tanlov (2026): Prisma — yangi loyiha, TS, DX muhim (eng ko'p tavsiya). TypeORM — NestJS bilan tabiiy (dekorator — 6.13, 8). Sequelize — mavjud loyiha, JS. Uchchovi ham yaxshi; Prisma — zamonaviy yetakchi.
2.18. Xavfsizlik va best practices (14)
PrismaClient singleton (bir marta — 2.10)
Migration (migrate dev/deploy — qo'lda emas — 2.7, 14)
include o'ylab (N+1 oldini oling, ortiqcha emas — 2.12, 2.16)
select bilan kerakli maydonlar (maxfiy yashiring — parol — 2.11)
Tranzaksiya ($transaction — ko'p yozuv — 2.14)
$queryRaw parametrli (injection — 14, 2.16)
DATABASE_URL .env'da (14, 5.8)
log: ["query"] (dev) — SQL ko'rish (2.16)3. Sintaksis — tez ma'lumotnoma
// schema.prisma (2.4)
model User { id Int @id @default(autoincrement()); email String @unique; orders Order[] }import { PrismaClient } from "@prisma/client";
const prisma = new PrismaClient(); // singleton (2.10)
await prisma.user.create({ data: {...} }); // C (2.9)
await prisma.user.findUnique({ where: { id } }); // R
await prisma.user.findMany({ where: { yosh: { gt: 18 } }, include: { orders: true } }); // (2.11, 2.12)
await prisma.user.update({ where: { id }, data: {...} }); // U
await prisma.user.delete({ where: { id } }); // D
await prisma.$transaction(async (tx) => {...}); // tranzaksiya (2.14)npx prisma migrate dev --name x # migrate (2.7)
npx prisma generate # client (2.8)
npx prisma studio # GUI (2.15)4. Batafsil kod namunalari
Misol 1 — To'liq schema (2.4-2.6)
// prisma/schema.prisma
generator client { provider = "prisma-client-js" }
datasource db { provider = "postgresql"; url = env("DATABASE_URL") }
model User {
id Int @id @default(autoincrement())
ism String
email String @unique
parol String // hash (5.15)
rol Role @default(USER)
orders Order[] // one-to-many (2.6)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@map("users")
}
model Order {
id Int @id @default(autoincrement())
user User @relation(fields: [userId], references: [id], onDelete: Cascade) // FK (6.6: 2.7)
userId Int
summa Decimal @db.Decimal(10, 2)
holat OrderStatus @default(YANGI)
items OrderItem[]
createdAt DateTime @default(now())
@@index([userId]) // indeks (6.10)
@@map("orders")
}
model Product {
id Int @id @default(autoincrement())
nom String
narx Decimal @db.Decimal(10, 2)
zaxira Int @default(0)
items OrderItem[]
@@map("products")
}
model OrderItem { // many-to-many junction (qo'lda — qo'shimcha maydon bilan)
order Order @relation(fields: [orderId], references: [id])
orderId Int
product Product @relation(fields: [productId], references: [id])
productId Int
miqdor Int
narx Decimal @db.Decimal(10, 2) // snapshot (6.3: Misol 7)
@@id([orderId, productId]) // composite PK
@@map("order_items")
}
enum Role { USER ADMIN }
enum OrderStatus { YANGI TASDIQLANDI YETKAZILDI BEKOR }Misol 2 — Client singleton (2.10)
// lib/prisma.js
import { PrismaClient } from "@prisma/client";
import { config } from "../config/index.js";
const globalForPrisma = globalThis;
export const prisma =
globalForPrisma.prisma ||
new PrismaClient({
log: config.isProd ? ["error"] : ["query", "warn", "error"], // dev'da SQL log (2.16)
});
if (!config.isProd) globalForPrisma.prisma = prisma; // hot-reload (2.10)Misol 3 — CRUD service (type-safe — 2.9, 2.11)
import { prisma } from "../lib/prisma.js";
export const UserService = {
yarat: (data) => prisma.user.create({
data,
select: { id: true, ism: true, email: true, rol: true }, // parolsiz (2.18)
}),
topId: (id) => prisma.user.findUnique({
where: { id }, select: { id: true, ism: true, email: true }, // parolsiz
}),
emailTop: (email) => prisma.user.findUnique({ where: { email } }), // parol bilan (login — 5.15)
royxat: ({ page = 1, limit = 20, qidiruv, rol }) => prisma.user.findMany({
where: {
...(rol && { rol }),
...(qidiruv && { ism: { contains: qidiruv, mode: "insensitive" } }), // qidiruv (2.11)
},
select: { id: true, ism: true, email: true, rol: true },
take: limit, skip: (page - 1) * limit, // sahifalash (2.11)
orderBy: { createdAt: "desc" },
}),
yangila: (id, data) => prisma.user.update({ where: { id }, data }),
ochir: (id) => prisma.user.delete({ where: { id } }),
};Misol 4 — Relations: include (eager — 2.12)
// Buyurtma + user + mahsulotlar (nested include — JOIN — 2.12)
export const buyurtmaToliq = (id) => prisma.order.findUnique({
where: { id },
include: {
user: { select: { ism: true, email: true } }, // user (kerakli)
items: { include: { product: { select: { nom: true, narx: true } } } }, // ichma-ich
},
});
// Natija TYPE-SAFE: order.user.ism, order.items[0].product.nom (autocompletion — 2.2)
// User + faqat tugallangan buyurtmalari (shartli include)
export const userFaol = (userId) => prisma.user.findUnique({
where: { id: userId },
include: { orders: { where: { holat: "TUGALLANDI" }, orderBy: { createdAt: "desc" } } },
});Misol 5 — Nested write (bog'liq birga — 2.13)
// Ro'yxatdan o'tish + boshlang'ich profil BIRGA (nested — atomik — 2.13)
export const royxatdanOtish = (data) => prisma.user.create({
data: {
ism: data.ism, email: data.email, parol: data.parolHash,
profile: { // bog'liq profil birga
create: { bio: "", avatar: null },
},
},
include: { profile: true },
});
// Buyurtma + items birga (nested — 2.13)
export const buyurtmaYarat = (userId, items) => prisma.order.create({
data: {
userId,
summa: items.reduce((s, i) => s + i.narx * i.miqdor, 0),
items: { create: items }, // items birga (bir tranzaksiya)
},
include: { items: true },
});Misol 6 — Tranzaksiya (interactive — 2.14)
// Pul o'tkazish — interactive transaction (murakkab mantiq — 2.14, 6.9)
export async function pulOtkaz(fromId, toId, summa) {
return prisma.$transaction(async (tx) => { // tx — tranzaksiya client
// Yechish (atomik decrement — 6.9: 2.11)
const from = await tx.account.update({
where: { id: fromId },
data: { balans: { decrement: summa } },
});
if (from.balans.lessThan(0)) { // Decimal taqqoslash
throw new Error("Balans yetarli emas"); // avtomatik ROLLBACK
}
// Qo'shish
await tx.account.update({ where: { id: toId }, data: { balans: { increment: summa } } });
// Log
await tx.transfer.create({ data: { fromId, toId, summa } });
});
// xato avtomatik rollback; muvaffaqiyat commit (6.9: ACID)
}Misol 7 — Zaxira (lock + tranzaksiya — 6.9: 2.13)
// Buyurtma + zaxira kamaytirish (atomik — 6.9)
export async function buyurtmaZaxira(userId, items) {
return prisma.$transaction(async (tx) => {
for (const item of items) {
// Atomik: zaxira yetarli bo'lsa kamaytir (updateMany count bilan)
const r = await tx.product.updateMany({
where: { id: item.productId, zaxira: { gte: item.miqdor } }, // shart bilan
data: { zaxira: { decrement: item.miqdor } },
});
if (r.count === 0) throw new Error("Zaxira yetarli emas"); // rollback
}
return tx.order.create({
data: { userId, items: { create: items }, summa: 0 }, // (summa hisoblanadi)
include: { items: true },
});
});
}Misol 8 — Express + xato boshqaruvi (5.6, 5.10)
import { Prisma } from "@prisma/client";
import { UserService } from "../services/userService.js";
export const userYarat = async (req, res, next) => {
try {
const user = await UserService.yarat(req.body); // (validatsiya — 5.9)
res.status(201).json({ success: true, data: user }); // (5.7)
} catch (err) {
if (err instanceof Prisma.PrismaClientKnownRequestError) {
if (err.code === "P2002") { // unique buzildi (2.18)
return res.status(409).json({ error: "Email band" }); // (5.10)
}
if (err.code === "P2025") { // topilmadi
return res.status(404).json({ error: "Topilmadi" });
}
}
next(err);
}
};
// Prisma xato kodlari: P2002 (unique), P2025 (not found), P2003 (FK)Misol 9 — Raw query (murakkab — 2.16)
// Murakkab so'rov (window — 6.7) — raw, lekin type-safe parametr (14)
const topMijozlar = await prisma.$queryRaw`
SELECT u.ism, SUM(o.summa) AS jami,
RANK() OVER (ORDER BY SUM(o.summa) DESC) AS reyting
FROM users u JOIN orders o ON u.id = o."userId"
WHERE o.holat = 'TUGALLANDI'
GROUP BY u.id, u.ism
LIMIT ${10}
`;
// $queryRaw — tagged template (parametrlar avtomatik xavfsiz — injection'siz — 14)5. To'g'ri va noto'g'ri holatlar
1) Har joyda yangi PrismaClient
// ko'p instance ulanish tugaydi (2.10)
function handler() { const prisma = new PrismaClient(); ... }
// singleton (bir marta — Misol 2)
import { prisma } from "../lib/prisma.js";2) N+1 (include o'rniga tsikl)
// N+1 (2.16)
for (const u of users) await prisma.order.findMany({ where: { userId: u.id } });
// include
await prisma.user.findMany({ include: { orders: true } });3) Parolni select'siz qaytarish
// parol ham keladi (14, 2.18)
await prisma.user.findUnique({ where: { id } });
// select (kerakli maydonlar)
await prisma.user.findUnique({ where: { id }, select: { id: true, email: true } });4) Qo'lda schema o'zgartirish (migratesiz)
DB'da qo'lda ALTER (schema bilan nomuvofiq — 2.7)
schema.prisma o'zgartiring migrate dev5) Raw query string birlashtirish
// injection (14, 2.16)
prisma.$queryRawUnsafe(`SELECT * FROM users WHERE email = '${email}'`);
// tagged template / parametrli
prisma.$queryRaw`SELECT * FROM users WHERE email = ${email}`;6. Keng tarqalgan xatolar va yechimlari
Xato 1 — PrismaClientInitializationError
Sababi: DATABASE_URL noto'g'ri, DB ishlamayapti, yoki generate qilinmagan (2.3, 2.8). Yechimi: .env tekshiring; DB ishga tushiring; prisma generate.
Xato 2 — P2002 Unique constraint failed
Sababi: unique buzildi (email — 2.4). Yechimi: 409 qaytaring (Misol 8); oldindan tekshiring.
Xato 3 — P2025 Record not found
Sababi: update/delete'da yo'q qator 2.9-bob. Yechimi: 404 qaytaring; oldindan findUnique.
Xato 4 — Type xatosi (so'rov)
Sababi: schema o'zgardi, generate qilinmagan 2.8-bob. Yechimi: prisma generate (client yangilash).
Xato 5 — Migration konflikti
Sababi: schema va migration nomuvofiq, yoki qo'lda o'zgarish 2.7-bob. Yechimi: migrate status; dev'da migrate reset (ehtiyot — ma'lumot o'chadi).
Xato 6 — N+1 (sekin)
Sababi: tsiklda alohida so'rov 2.16-bob. Yechimi: include; log: ["query"] bilan tekshiring.
7. Integratsiya — bu mavzu stack'ning qayerida uchraydi
- SQL (6.4-6.10): Prisma SQL ustida; raw query.
- PostgreSQL/MySQL (6.5, 6.6): Prisma provider.
- Sequelize 6.11-bob: muqobil ORM (taqqoslash).
- TypeScript (7): type-safety — Prisma kuchi.
- Tranzaksiya/ACID 6.9-bob: $transaction.
- Indeks/N+1 6.10-bob: include, @@index.
- NestJS 8.3-bob: Prisma module.
- Next.js (13): Prisma (singleton — 2.10).
- Auth 5.15-bob: User model, parol.
- Xavfsizlik (14): injection ($queryRaw parametrli).
8. Eng yaxshi amaliyotlar (best practices)
- PrismaClient singleton (bir marta — 2.10).
- Migration (migrate dev/deploy — qo'lda emas — 2.7, 14).
- include o'ylab (N+1 oldini oling, ortiqcha emas — 2.12, 2.16).
- select bilan kerakli maydonlar (maxfiy yashiring — parol — 2.11, 2.18).
- Tranzaksiya ($transaction — ko'p yozuv; nested write — 2.13, 2.14).
- Type-safety'dan foydalaning (autocompletion, kompilyatsiya xatosi — 2.2).
- $queryRaw parametrli (tagged template — injection — 2.16, 14).
- log: ["query"] (dev) — SQL ko'rish 2.16-bob.
- Xatolarni kod bo'yicha (P2002 409 — Misol 8, 5.10).
- Prisma Studio (dev — ma'lumot ko'rish — 2.15).
9. Amaliy loyiha: "Prisma bilan Type-Safe Backend"
Prisma'ni professional darajada mustahkamlash.
Maqsad
Prisma bilan to'liq, type-safe, migration-asosli backend qurish: schema, client, relations, nested write va tranzaksiya.
Talablar (requirements)
- Schema: User/Order/Product/OrderItem — relations, enum, indeks, @db turlar (Misol 1, 2.4-2.6).
- Migrate + generate: schema DB client (2.7, 2.8).
- Client singleton: lib/prisma.js (Misol 2, 2.10).
- CRUD service: type-safe; select (parolsiz); qidiruv/sahifalash (Misol 3, 2.11).
- Relations: include (nested, shartli — Misol 4, 2.12).
- Nested write: user+profil yoki order+items birga (Misol 5, 2.13).
- Tranzaksiya: pul o'tkazish / zaxira (interactive — Misol 6, 7, 2.14).
- Express: xato kodlari (P2002409 — Misol 8).
- Raw query: murakkab so'rov (window — parametrli — Misol 9, 2.16).
- Prisma Studio: ma'lumotni ko'rish 2.15-bob.
Maslahatlar (hint)
- Singleton: globalThis (hot-reload — 2.10, 1-xato).
- include: N+1 oldini oladi (2.12, 2.16).
- select: parolsiz (2.18, 3-xato).
- Tranzaksiya:
$transaction(async tx => {})2.14-bob. - increment/decrement: atomik 6.9-bob.
- $queryRaw: tagged template (injection — 2.16, 5-xato).
- P2002 (unique), P2025 (not found) — Misol 8.
"Tayyor" mezonlari (acceptance criteria)
- Schema (relations, enum, indeks).
- Migrate + generate ishlaydi.
- Client singleton.
- CRUD type-safe (select — parolsiz).
- include (nested, shartli).
- Nested write (bog'liq birga).
- Tranzaksiya ($transaction).
- Xato kodlari (P2002409).
- Raw query (parametrli).
- N+1 yo'q (include).
Yechim kodi ataylab berilmagan — bu loyihani o'zingiz yozib ko'ring.
10. Xulosa va keyingi bobga ko'prik
Bu bobda zamonaviy, type-safe ORM — Prisma ni chuqur o'rgandik:
- Prisma (schema + client + migrate — 2.1); type-safety (kompilyatsiya xatosi, autocompletion — 2.2).
- Schema (schema.prisma — model/atribut/enum — 2.4, 2.5); relations (@relation, avtomatik m:n junction — 2.6); migrate (avtomatik — 2.7), generate (client — 2.8).
- Client (findUnique/findMany/create — 2.9, type-safe; singleton — 2.10); operatorlar 2.11-bob; include (eager JOIN — 2.12).
- Nested write (bog'liq birga — atomik — 2.13); tranzaksiya ($transaction — 2.14); Prisma Studio 2.15-bob; raw query 2.16-bob; taqqoslash 2.17-bob.
Keyingi bob — 6.13-bob: ORM — TypeORM (entity, repository, relations). Prisma (schema-first) ni bildik; endi uchinchi ORM — TypeORM ni o'rganamiz. TypeORM — class va dekorator asosida (Prisma'dan boshqacha), va NestJS (8) bilan eng tabiiy ishlaydi. Entity, repository pattern, relations — chuqur. Bu — NestJS qismiga (8) tayyorgarlik.
Foydalanilgan rasmiy/ishonchli manbalar
- prisma.io/docs — Prisma Schema, Client, Migrate, Relations, Transactions, Best practices
- prisma.io — Relation queries (include, nested write); Prisma 7 (2025 — TypeScript runtime)
- tech-insider — Prisma ORM tutorial 2026 (type-safe API)
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!