MikroORM
Bu retsept foydalanuvchilarga Nest ichida MikroORM bilan ishlashni boshlashga yordam beradi. MikroORM Data Mapper, Unit of Work va Identity Map patternlariga asoslangan, Node.js uc
Bu retsept foydalanuvchilarga Nest ichida MikroORM bilan ishlashni boshlashga yordam beradi. MikroORM Data Mapper, Unit of Work va Identity Map patternlariga asoslangan, Node.js uchun TypeScript ORM. U TypeORM ga yaxshi muqobil bo'lib, TypeORM dan migratsiya qilish ancha oson bo'lishi kerak. MikroORM ning to'liq hujjatlarini bu yerda topishingiz mumkin.
@mikro-orm/nestjs uchinchi tomon paketi bo'lib, NestJS core jamoasi tomonidan boshqarilmaydi. Kutubxona bilan bog'liq muammolarni tegishli repoda xabar bering.
O'rnatish
MikroORM ni Nest ga integratsiya qilishning eng oson yo'li @mikro-orm/nestjs moduli orqali.
Uni Nest, MikroORM va drayver bilan birga o'rnating:
1$ npm i @mikro-orm/core @mikro-orm/nestjs @mikro-orm/sqliteMikroORM postgres, sqlite va mongo ni ham qo'llab-quvvatlaydi. Barcha drayverlar uchun rasmiy hujjat ga qarang.
O'rnatish yakunlangach, MikroOrmModule ni ildiz AppModule ga import qilishimiz mumkin.
1import { SqliteDriver } from '@mikro-orm/sqlite';
2
3@Module({
4 imports: [
5 MikroOrmModule.forRoot({
6 entities: ['./dist/entities'],
7 entitiesTs: ['./src/entities'],
8 dbName: 'my-db-name.sqlite3',
9 driver: SqliteDriver,
10 }),
11 ],
12 controllers: [AppController],
13 providers: [AppService],
14})
15export class AppModule {}forRoot() metodi MikroORM paketidagi init() dagi kabi konfiguratsiya obyektini qabul qiladi. To'liq konfiguratsiya hujjati uchun ushbu sahifa ga qarang.
Boshqa variant sifatida, mikro-orm.config.ts konfiguratsiya faylini yaratib, forRoot() ni argumentlarsiz chaqirib CLI ni sozlashimiz mumkin.
1@Module({
2 imports: [
3 MikroOrmModule.forRoot(),
4 ],
5 ...
6})
7export class AppModule {}Lekin tree shaking ishlatadigan build vositalarida bu ishlamaydi, bunday holatda konfiguratsiyani aniq ko'rsatgan ma'qul:
1import config from './mikro-orm.config'; // your ORM config
2
3@Module({
4 imports: [
5 MikroOrmModule.forRoot(config),
6 ],
7 ...
8})
9export class AppModule {}Shundan so'ng EntityManager butun loyiha bo'ylab inject qilish uchun mavjud bo'ladi (boshqa joyda modul import qilmasdan).
1// Import everything from your driver package or `@mikro-orm/knex`
2import { EntityManager, MikroORM } from '@mikro-orm/sqlite';
3
4@Injectable()
5export class MyService {
6 constructor(
7 private readonly orm: MikroORM,
8 private readonly em: EntityManager,
9 ) {}
10}EntityManager@mikro-orm/driver paketidan import qilinishiga e'tibor bering, bu yerda drayver mysql, sqlite, postgres yoki foydalanayotgan drayveringiz. Agar qaramlik sifatida @mikro-orm/knex o'rnatilgan bo'lsa, EntityManager ni o'sha yerdan ham import qilishingiz mumkin.
Repositorylar
MikroORM repository dizayn patternini qo'llab-quvvatlaydi. Har bir entitet uchun repository yaratishimiz mumkin. Repositorylar bo'yicha to'liq hujjatni bu yerda o'qing. Joriy scope da qaysi repositorylar ro'yxatdan o'tishi kerakligini forFeature() metodi orqali belgilashingiz mumkin. Masalan:
Bazaviy entitetlarni forFeature() orqali ro'yxatdan o'tkazmang, chunki ular uchun repositorylar yo'q. Biroq, bazaviy entitetlar forRoot() dagi ro'yxatning (yoki umumiy ORM konfiguratsiyasining) bir qismi bo'lishi kerak.
1// photo.module.ts
2@Module({
3 imports: [MikroOrmModule.forFeature([Photo])],
4 providers: [PhotoService],
5 controllers: [PhotoController],
6})
7export class PhotoModule {}and import it into the root AppModule:
1// app.module.ts
2@Module({
3 imports: [MikroOrmModule.forRoot(...), PhotoModule],
4})
5export class AppModule {}Shu tarzda PhotoRepository ni PhotoService ga @InjectRepository() dekoratori yordamida inject qilishimiz mumkin:
1@Injectable()
2export class PhotoService {
3 constructor(
4 @InjectRepository(Photo)
5 private readonly photoRepository: EntityRepository<Photo>,
6 ) {}
7}Custom repositorylardan foydalanish
Custom repositorylardan foydalanganda @InjectRepository() dekoratori endi kerak emas, chunki Nest DI klassga havola asosida resolve qiladi.
1// `**./author.entity.ts**`
2@Entity({ repository: () => AuthorRepository })
3export class Author {
4 // to allow inference in `em.getRepository()`
5 [EntityRepositoryType]?: AuthorRepository;
6}
7
8// `**./author.repository.ts**`
9export class AuthorRepository extends EntityRepository<Author> {
10 // your custom methods...
11}Custom repository nomi getRepositoryToken() qaytaradigan nom bilan bir xil bo'lgani uchun @InjectRepository() dekoratori endi kerak emas:
1@Injectable()
2export class MyService {
3 constructor(private readonly repo: AuthorRepository) {}
4}Entitetlarni avtomatik yuklash
Entitetlarni qo'lda connection parametrlaridagi entities massiviga qo'shish zerikarli bo'lishi mumkin. Bundan tashqari, entitetlarga ildiz moduli orqali murojaat qilish ilova domen chegaralarini buzadi va implementatsiya tafsilotlarining boshqa qismlarga sizib chiqishiga sabab bo'ladi. Bu muammoni hal qilish uchun statik glob yo'llardan foydalanish mumkin.
Ammo glob yo'llar webpack tomonidan qo'llab-quvvatlanmasligini unutmang, shuning uchun monorepo ichida ilova qurayotgan bo'lsangiz, ulardan foydalana olmaysiz. Bu muammoni hal qilish uchun alternativ yechim taqdim etilgan. Entitetlarni avtomatik yuklash uchun konfiguratsiya obyektining (forRoot() metodiga uzatiladigan) autoLoadEntities xususiyatini true ga o'rnating:
1@Module({
2 imports: [
3 MikroOrmModule.forRoot({
4 ...
5 autoLoadEntities: true,
6 }),
7 ],
8})
9export class AppModule {}Bu parametr ko'rsatilgan bo'lsa, forFeature() orqali ro'yxatdan o'tkazilgan har bir entitet konfiguratsiya obyektidagi entities massiviga avtomatik qo'shiladi.
forFeature() orqali ro'yxatdan o'tkazilmagan, lekin entitetdan (aloqa orqali) murojaat qilinadigan entitetlar autoLoadEntities yordamida kiritilmaydi.
autoLoadEntities MikroORM CLI ga ham ta'sir qilmaydi - u yerda ham entitetlarning to'liq ro'yxati ko'rsatilgan CLI konfiguratsiyasi kerak. Boshqa tomondan, u yerda globlardan foydalanishimiz mumkin, chunki CLI webpackdan o'tmaydi.
Serialization
MikroORM har bir entitet aloqasini yaxshiroq type-safety uchun Reference<T> yoki Collection<T> obyektiga o'rab beradi. Bu Nest'ning o'rnatilgan serializerini o'ralgan aloqalardan bexabar qiladi. Boshqacha aytganda, HTTP yoki WebSocket handlerlaridan MikroORM entitetlarini qaytarsangiz, ularning barcha aloqalari serializatsiya qilinmaydi.
Yaxshiyamki, MikroORM ClassSerializerInterceptor o'rniga ishlatish mumkin bo'lgan serialization API ni taqdim etadi.
1@Entity()
2export class Book {
3 @Property({ hidden: true }) // Equivalent of class-transformer's `@Exclude`
4 hiddenField = Date.now();
5
6 @Property({ persist: false }) // Similar to class-transformer's `@Expose()`. Will only exist in memory, and will be serialized.
7 count?: number;
8
9 @ManyToOne({
10 serializer: (value) => value.name,
11 serializedName: 'authorName',
12 }) // Equivalent of class-transformer's `@Transform()`
13 author: Author;
14}Queue larda request scope handlerlar
Hujjatda aytilganidek, har bir so'rov uchun toza holat kerak. Bu middleware orqali ro'yxatdan o'tgan RequestContext yordamchisi tufayli avtomatik boshqariladi.
Lekin middleware lar faqat odatiy HTTP so'rovlarini bajaradi, agar shundan tashqarida request scope metod kerak bo'lsa-chi? Masalan, queue handlerlari yoki rejalashtirilgan vazifalar.
@CreateRequestContext() dekoratoridan foydalanishimiz mumkin. Avval MikroORM nusxasini joriy kontekstga inject qilishingiz kerak bo'ladi, u siz uchun kontekst yaratishda ishlatiladi. Dekorator parda ortida yangi request kontekstni ro'yxatdan o'tkazadi va metodni shu kontekst ichida bajaradi.
1@Injectable()
2export class MyService {
3 constructor(private readonly orm: MikroORM) {}
4
5 @CreateRequestContext()
6 async doSomething() {
7 // this will be executed in a separate context
8 }
9}Nomidan ko'rinib turibdiki, bu dekorator har doim yangi kontekst yaratadi; uning alternativasi @EnsureRequestContext esa faqat boshqa kontekst ichida bo'lmagandagina yaratadi.
Testlash
@mikro-orm/nestjs paketi repositoryni mock qilish uchun berilgan entitet asosida tayyor token qaytaruvchi getRepositoryToken() funksiyasini ochib beradi.
1@Module({
2 providers: [
3 PhotoService,
4 {
5 // or when you have a custom repository: `provide: PhotoRepository`
6 provide: getRepositoryToken(Photo),
7 useValue: mockedRepository,
8 },
9 ],
10})
11export class PhotoModule {}Misol
NestJS va MikroORM bilan real loyiha misolini bu yerda topishingiz mumkin.