Давайте продолжим изучение более продвинутых вариантов использования TypeORM и NestJS. На этот раз мы сосредоточимся на использовании транзакций и прослушивателей событий для лучшей согласованности и обработки данных.

Транзакции гарантируют, что ряд операций с базой данных будет выполняться атомарно, то есть либо все операции будут успешными, либо ни одна. TypeORM предоставляет удобный способ управления транзакциями с помощью queryRunner:

import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository, Connection } from 'typeorm';
import { User } from '../user/user.entity';
import { Post } from '../post/post.entity';

@Injectable()
export class PostService {
  constructor(
    private connection: Connection,
    @InjectRepository(User) private userRepository: Repository<User>,
    @InjectRepository(Post) private postRepository: Repository<Post>,
  ) {}
  async createPostWithTransaction(userId: number, post: Post): Promise<Post> {
    const queryRunner = this.connection.createQueryRunner();
    await queryRunner.connect();
    await queryRunner.startTransaction();
    try {
      const user = await queryRunner.manager.findOne(User, userId);
      if (!user) {
        throw new Error('User not found');
      }
      post.user = user;
      const savedPost = await queryRunner.manager.save(post);
      await queryRunner.commitTransaction();
      return savedPost;
    } catch (error) {
      await queryRunner.rollbackTransaction();
      throw error;
    } finally {
      await queryRunner.release();
    }
  }
}

В этом примере мы использовали createQueryRunner для создания нового экземпляра queryRunner. Затем мы подключились и начали транзакцию. Если какая-либо операция в блоке try завершится ошибкой, транзакция будет отменена, и никакие изменения не будут зафиксированы в базе данных.

Теперь давайте обсудим прослушиватели событий. TypeORM позволяет создавать прослушиватели, которые вызываются до или после определенных событий сущности, таких как вставка, обновление или удаление. Эти прослушиватели могут быть полезны для проверки, ведения журнала или других задач. Вот пример прослушивателя событий для сущности Post:

import {
  EntitySubscriberInterface,
  EventSubscriber,
  InsertEvent,
  UpdateEvent,
} from 'typeorm';
import { Post } from '../post/post.entity';

@EventSubscriber()
export class PostSubscriber implements EntitySubscriberInterface<Post> {
  listenTo() {
    return Post;
  }
  beforeInsert(event: InsertEvent<Post>) {
    console.log(`BEFORE POST INSERTED: `, event.entity);
  }
  afterInsert(event: InsertEvent<Post>) {
    console.log(`AFTER POST INSERTED: `, event.entity);
  }
  beforeUpdate(event: UpdateEvent<Post>) {
    console.log(`BEFORE POST UPDATED: `, event.entity);
  }
  afterUpdate(event: UpdateEvent<Post>) {
    console.log(`AFTER POST UPDATED: `, event.entity);
  }
}

В этом примере мы создали PostSubscriber, который прослушивает события объекта Post. Мы реализовали такие методы, как beforeInsert, afterInsert, beforeUpdate и afterUpdate для выполнения действий до и после соответствующих событий.

Освоив транзакции и прослушиватели событий, вы сможете создавать более надежные и удобные в сопровождении приложения с помощью NestJS и TypeORM. Продолжайте в том же духе! 🚀