مستودعات TypeORM مخصصة
أنشئ مستودعات مخصصة لتغليف استعلامات قاعدة البيانات المعقدة وتحسين تنظيم الشيفرة وقابليتها لإعادة الاستخدام.
مستودعات TypeORM مخصصة درس مجاني في NestJS Enterprise Backend APIs على CoddyKit. هذا هو الدرس 1 من أصل 3. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في NestJS Enterprise Backend APIs، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة NestJS Enterprise Backend APIs 3 دروس في المجموع.
بعض أجزاء هذا الدرس لم تُترجم بعد وتظهر باللغة الإنجليزية.
Beyond Basic CRUD
TypeORM's default Repository offers basic operations like save, find, and delete. These are great for simple tasks.
However, real-world applications often need more complex queries or domain-specific data retrieval logic.
Encapsulating Complex Queries
Without custom repositories, complex database queries might end up directly in your service layer. This can make services bloated and harder to maintain.
- Cleaner Services: Services focus on business logic, not database specifics.
- Reusability: Complex queries can be reused across different parts of your application.
- Testability: Easier to test database interactions in isolation.
Creating a Custom Repository
To create a custom repository, you define a class that extends TypeORM's Repository<Entity>. You must also decorate it with @EntityRepository(Entity) to link it to a specific entity.
import { Entity, PrimaryGeneratedColumn, Column } from 'typeorm';
@Entity()
export class User {
@PrimaryGeneratedColumn()
id: number;
@Column()
name: string;
@Column({ unique: true })
email: string;
@Column({ default: true })
isActive: boolean;
}
// src/user/user.repository.ts
import { EntityRepository, Repository } from 'typeorm';
import { User } from './user.entity';
@EntityRepository(User)
export class UserRepository extends Repository<User> {
// Custom methods will go here
}Injecting the Custom Repository
Once defined, you can inject your custom repository into NestJS services or controllers using the @InjectRepository() decorator.
Remember to pass your custom repository class as an argument to @InjectRepository().
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { UserRepository } from './user.repository';
import { User } from './user.entity';
@Injectable()
export class UserService {
constructor(
@InjectRepository(UserRepository)
private userRepository: UserRepository,
) {}
async findAllActive(): Promise<User[]> {
// This method will be defined in the custom repo
return this.userRepository.findActiveUsers();
}
}Adding a Custom Method
Inside your custom repository, you can add methods that encapsulate specific query logic. These methods can use the default Repository methods or TypeORM's Query Builder.
Let's add methods to find all active users and find a user by email.
// src/user/user.repository.ts (updated)
import { EntityRepository, Repository } from 'typeorm';
import { User } from './user.entity';
@EntityRepository(User)
export class UserRepository extends Repository<User> {
async findActiveUsers(): Promise<User[]> {
return this.find({ isActive: true });
}
async findByEmail(email: string): Promise<User | undefined> {
return this.findOne({ email });
}
}Custom Repo Workflow
Here's the typical flow: you define your Entity, then your Custom Repository extending Repository<Entity>, and finally inject it into your Service.
// 1. user.entity.ts
import { Entity, PrimaryGeneratedColumn, Column } from 'typeorm';
@Entity() export class User {
@PrimaryGeneratedColumn() id: number;
@Column() name: string;
@Column({ unique: true }) email: string;
@Column({ default: true }) isActive: boolean;
}
// 2. user.repository.ts
import { EntityRepository, Repository } from 'typeorm';
import { User } from './user.entity';
@EntityRepository(User)
export class UserRepository extends Repository<User> {
async findActiveUsers(): Promise<User[]> {
return this.find({ isActive: true });
}
}
// 3. user.service.ts
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { UserRepository } from './user.repository';
import { User } from './user.entity';
@Injectable()
export class UserService {
constructor(
@InjectRepository(UserRepository)
private userRepository: UserRepository,
) {}
async getAllActive(): Promise<User[]> {
return this.userRepository.findActiveUsers();
}
}Module Configuration
For NestJS to properly manage the TypeORM repositories, your module needs to import TypeOrmModule.forFeature() with your entities. The @EntityRepository decorator handles the TypeORM-side registration, allowing injection.
// src/user/user.module.ts
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { User } from './user.entity';
import { UserService } from './user.service';
import { UserController } from './user.controller';
@Module({
imports: [
TypeOrmModule.forFeature([User]) // Only entities here
],
providers: [UserService, UserController],
exports: [UserService] // Export service if used elsewhere
})
export class UserModule {}Leveraging Query Builder
For more complex queries, custom repositories often use TypeORM's powerful Query Builder. This allows you to construct dynamic queries with joins, conditions, and more.
Let's add a method to find users who are active and have a specific name pattern.
// src/user/user.repository.ts (extended)
import { EntityRepository, Repository } from 'typeorm';
import { User } from './user.entity';
import { MoreThan } from 'typeorm'; // Example for complex query
@EntityRepository(User)
export class UserRepository extends Repository<User> {
async findActiveUsers(): Promise<User[]> {
return this.find({ isActive: true });
}
async findByNamePattern(pattern: string): Promise<User[]> {
return this.createQueryBuilder('user')
.where('user.name LIKE :pattern', { pattern: `%${pattern}%` })
.andWhere('user.isActive = :isActive', { isActive: true })
.getMany();
}
}Check Your Understanding
Consider the following custom repository and service:
// product.repository.ts
import { EntityRepository, Repository, MoreThan } from 'typeorm';
import { Product } from './product.entity'; // Assume Product entity exists
@EntityRepository(Product)
export class ProductRepository extends Repository<Product> {
async findAvailableProducts(): Promise<Product[]> {
return this.find({ where: { stock: MoreThan(0), isActive: true } });
}
}
// product.service.ts
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { ProductRepository } from './product.repository';
import { Product } from './product.entity'; // Assume Product entity exists
@Injectable()
export class ProductService {
constructor(
@InjectRepository(ProductRepository)
private productRepo: ProductRepository,
) {}
async getProducts(): Promise<Product[]> {
return this.productRepo.findAvailableProducts();
}
}Custom Repositories Summary
In this lesson, we explored custom TypeORM repositories. We learned that they are a powerful pattern to:
- Encapsulate complex, reusable database query logic.
- Keep your NestJS services clean and focused on business rules.
- Improve code organization, reusability, and testability.
By extending TypeORM's Repository and using @EntityRepository, you can define domain-specific methods that make your data access layer much more robust.
تعلم TypeScript مع معلم ذكاء اصطناعي — مجانًا
اكتب وقم بتشغيل أكوادك الفعلية في المتصفح، واحصل على مساعدة فورية من معلم ذكاء اصطناعي متاح 24/7، واستمر من حيث توقفت على الويب أو في التطبيق.
- الدورات
- 20
- الدروس
- 76
الأسئلة الشائعة
هل درس «مستودعات TypeORM مخصصة» مجاني؟
نعم — نص درس «مستودعات TypeORM مخصصة» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة NestJS Enterprise Backend APIs، انتقل إلى CoddyKit PRO. تتضمن دورة NestJS Enterprise Backend APIs 3 دروس في المجموع.
ماذا ستتعلم في «مستودعات TypeORM مخصصة»؟
أنشئ مستودعات مخصصة لتغليف استعلامات قاعدة البيانات المعقدة وتحسين تنظيم الشيفرة وقابليتها لإعادة الاستخدام. تتمرن على NestJS Enterprise Backend APIs مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.
هل أحتاج إلى خبرة سابقة لأبدأ NestJS Enterprise Backend APIs؟
لا تُشترط خبرة سابقة. NestJS Enterprise Backend APIs على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 1 من أصل 3.
كم من الوقت يستغرق درس «مستودعات TypeORM مخصصة»؟
معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.
هل يمكنني كتابة وتشغيل أكواد في درس NestJS Enterprise Backend APIs هذا؟
نعم. كل درس في NestJS Enterprise Backend APIs يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.
جميع الدروس في هذه الدورة
- مستودعات TypeORM مخصصة
- المعاملات وعمليات الترحيل
- تهيئة قاعدة البيانات بالبيانات واختبارها