Ma'lumotlar bazasi (TypeORM)
Haqiqiy ilovalar ma'lumotni doimiy saqlashi kerak โ bu esa ma'lumotlar bazasini talab qiladi. NestJS eng mashhur ORM (Object-Relational Mapping) kutubxonalari bilan chuqur integratsiyaga ega. Ushbu darsda TypeORM orqali bazaga ulanishni, @Entity bilan jadval yaratishni, Repository shablonini va to'liq CRUD servisni yozishni o'rganamiz.
ORM nima va nega TypeORM?
ORM โ bu ma'lumotlar bazasidagi jadvallarni kodingizdagi obyektlar bilan bog'lovchi qatlam. U sizni SQL so'rovlarini qo'lda yozishdan qutqaradi: siz obyektlar bilan ishlaysiz, ORM esa ularni SQL'ga o'giradi. TypeORM โ TypeScript uchun eng mashhur ORM'lardan biri va NestJS bilan rasmiy integratsiyaga ega.
- SQL o'rniga TypeScript klasslari va metodlar bilan ishlaysiz;
- PostgreSQL, MySQL, SQLite, MariaDB va boshqalarni qo'llab-quvvatlaydi;
- Migratsiyalar orqali baza sxemasini boshqarish imkoni;
- TypeScript tiplari bilan to'liq mos ishlaydi.
O'rnatish va ulanish
Avval kerakli paketlarni o'rnatamiz: NestJS'ning TypeORM adapteri, TypeORM'ning o'zi va PostgreSQL drayveri:
npm install @nestjs/typeorm typeorm pg
Endi bazaga ulanishni ildiz modulda sozlaymiz. TypeOrmModule.forRoot() ulanish parametrlarini qabul qiladi:
// src/app.module.ts
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
@Module({
imports: [
TypeOrmModule.forRoot({
type: 'postgres',
host: 'localhost',
port: 5432,
username: 'postgres',
password: 'parol',
database: 'mening_bazam',
entities: [__dirname + '/**/*.entity{.ts,.js}'],
synchronize: true, // Faqat ishlab chiqish (development) uchun!
}),
],
})
export class AppModule {}
synchronize: true baza sxemasini entity'laringizga qarab avtomatik yangilaydi. Bu ishlab chiqishda qulay, lekin ishlab chiqarishda (production) hech qachon ishlatmang โ u ma'lumotni yo'q qilishi mumkin. Production'da migratsiyalardan foydalaning.@Entity โ jadval e'loni
Entity โ bu ma'lumotlar bazasidagi jadvalni ifodalovchi klass. Har bir entity nusxasi jadvalning bir qatoriga, har bir xossa esa ustunga mos keladi. Entity'ni @Entity dekoratori bilan belgilaymiz:
// src/users/user.entity.ts
import {
Entity, PrimaryGeneratedColumn, Column, CreateDateColumn,
} from 'typeorm';
@Entity('users') // 'users' nomli jadval
export class User {
@PrimaryGeneratedColumn() // Avtomatik o'suvchi asosiy kalit (id)
id: number;
@Column({ length: 100 })
ism: string;
@Column({ unique: true }) // Takrorlanmas email
email: string;
@Column({ default: true })
faol: boolean;
@CreateDateColumn() // Yaratilgan sana avtomatik qo'yiladi
yaratilganSana: Date;
}
Asosiy ustun dekoratorlari:
@PrimaryGeneratedColumn()โ avtomatik o'suvchi asosiy kalit;@Column()โ oddiy ustun, parametrlargalength,unique,default,nullableberish mumkin;@CreateDateColumn()โ qator yaratilgan vaqtni avtomatik saqlaydi;@UpdateDateColumn()โ oxirgi yangilanish vaqtini avtomatik saqlaydi.
Repository shabloni
Repository โ bu ma'lum bir entity bilan ishlash uchun tayyor obyekt. U find, save, delete kabi metodlar orqali bazaga so'rov yuboradi. TypeORM har bir entity uchun avtomatik repository yaratadi.
Repository'ni service ichida ishlatish uchun ikki bosqich kerak. Avval feature modulda entity'ni ro'yxatdan o'tkazamiz โ TypeOrmModule.forFeature() orqali:
// src/users/users.module.ts
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { User } from './user.entity';
import { UsersService } from './users.service';
import { UsersController } from './users.controller';
@Module({
imports: [TypeOrmModule.forFeature([User])], // User repository'sini ochadi
providers: [UsersService],
controllers: [UsersController],
})
export class UsersModule {}
So'ng service ichida repository'ni @InjectRepository dekoratori orqali injektsiya qilamiz:
// src/users/users.service.ts
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { User } from './user.entity';
@Injectable()
export class UsersService {
constructor(
@InjectRepository(User)
private readonly usersRepo: Repository<User>,
) {}
}
Repository<User> โ bu generik tip. U repository aynan User entity bilan ishlashini bildiradi. Shu tufayli find yoki save chaqirganingizda TypeScript sizga to'g'ri tiplarni ko'rsatadi.To'liq CRUD service misoli
Endi barcha CRUD amallarini (Create, Read, Update, Delete) o'z ichiga olgan to'liq servisni yozamiz. Repository metodlariga e'tibor bering โ ular deyarli SQL yozmasdan hamma ishni bajaradi:
// src/users/users.service.ts
import { Injectable, NotFoundException } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { User } from './user.entity';
import { CreateUserDto } from './dto/create-user.dto';
@Injectable()
export class UsersService {
constructor(
@InjectRepository(User)
private readonly repo: Repository<User>,
) {}
// CREATE โ yangi foydalanuvchi yaratish
async create(dto: CreateUserDto): Promise<User> {
const user = this.repo.create(dto); // Obyekt tayyorlaydi
return this.repo.save(user); // Bazaga yozadi
}
// READ (barchasi)
async findAll(): Promise<User[]> {
return this.repo.find();
}
// READ (bittasi)
async findOne(id: number): Promise<User> {
const user = await this.repo.findOne({ where: { id } });
if (!user) {
throw new NotFoundException('Foydalanuvchi topilmadi: ' + id);
}
return user;
}
// UPDATE
async update(id: number, dto: Partial<CreateUserDto>): Promise<User> {
const user = await this.findOne(id); // Avval borligini tekshiramiz
Object.assign(user, dto); // Yangi qiymatlarni qo'shamiz
return this.repo.save(user);
}
// DELETE
async remove(id: number): Promise<void> {
const user = await this.findOne(id);
await this.repo.remove(user);
}
}
Eng ko'p ishlatiladigan repository metodlari:
create(dto)โ entity nusxasini tayyorlaydi (hali saqlamaydi);save(entity)โ bazaga yozadi (yangi bo'lsa INSERT, mavjud bo'lsa UPDATE);find()/findOne({ where })โ o'qish;remove(entity)โ o'chirish;count(),update(),delete()โ qo'shimcha amallar.
findOne topa olmasa null qaytaradi. Shuning uchun yuqoridagi kodda biz uni tekshirib, NotFoundException tashladik. NestJS bu istisnoni avtomatik 404 Not Found javobiga o'giradi โ bu qulay tayyor mexanizm.Controller bilan bog'lash
Endi servisni controller'ga ulaymiz. Controller ingichka qoladi โ u faqat so'rovni qabul qilib, servisga uzatadi:
// src/users/users.controller.ts
import {
Controller, Get, Post, Patch, Delete, Body, Param, ParseIntPipe,
} from '@nestjs/common';
import { UsersService } from './users.service';
import { CreateUserDto } from './dto/create-user.dto';
@Controller('users')
export class UsersController {
constructor(private readonly service: UsersService) {}
@Post()
create(@Body() dto: CreateUserDto) {
return this.service.create(dto);
}
@Get()
findAll() {
return this.service.findAll();
}
@Get(':id')
findOne(@Param('id', ParseIntPipe) id: number) {
return this.service.findOne(id);
}
@Delete(':id')
remove(@Param('id', ParseIntPipe) id: number) {
return this.service.remove(id);
}
}
Prisma bilan qisqacha taqqoslash
TypeORM yagona tanlov emas. So'nggi yillarda Prisma juda mashhur bo'ldi. U boshqacha yondashuvni tanlaydi: entity klasslari o'rniga alohida schema.prisma faylida sxema e'lon qilinadi va undan tiplar avtomatik generatsiya qilinadi.
// schema.prisma faylida sxema (TypeScript emas):
model User {
id Int @id @default(autoincrement())
ism String
email String @unique
faol Boolean @default(true)
}
- TypeORM: dekoratorlar bilan ishlaydi, NestJS uslubiga tabiiy mos keladi, moslashuvchan;
- Prisma: alohida sxema fayli, avtomatik generatsiya qilingan mustahkam tiplar, ajoyib developer tajribasi;
- Ikkalasi ham NestJS bilan yaxshi ishlaydi โ tanlov jamoa afzalligiga bog'liq.
Xulosa
- ORM baza jadvallarini kod obyektlariga bog'laydi, SQL yozishni kamaytiradi;
TypeOrmModule.forRoot()ildiz modulda ulanishni sozlaydi;- @Entity jadvalni,
@PrimaryGeneratedColumn/@Columnustunlarni belgilaydi; TypeOrmModule.forFeature([Entity])feature modulda repository'ni ochadi;- Repository
find,save,removemetodlari bilan CRUD amallarini bajaradi; - Topilmagan yozuv uchun
NotFoundExceptiontashlansa, NestJS avtomatik 404 qaytaradi; synchronize: truefaqat development uchun; production'da migratsiyalar ishlating;- Prisma โ TypeORM'ga zamonaviy muqobil, kuchli tip xavfsizligi bilan.