Запросы в AfterUpdate не работают должным образом в TypeORM - PullRequest
0 голосов
/ 14 июля 2020

У меня есть одна сущность в TypeORM, содержащая массив дочерних других сущностей:

MyEntity
  children (OneToMany)

Когда я удаляю один дочерний элемент (например, с ID = 2) и сохраняю этот объект, обновление запускается, как ожидалось структура в таблице дочерних объектов:

UPDATE "my_children_table" SET "myEntityId" = null WHERE "id" = 2 

У меня также есть подписчик, который прослушивает событие после обновления, которое также запускается, как ожидалось. Однако обновление не удаляет запись. Запись теперь осиротела с нулевым идентификатором отношения. В приведенном ниже примере я использую подписчика для очистки потерянных сущностей:

@EventSubscriber()
export class MyChildSubscriber implements EntitySubscriberInterface<MyChildEntity> {
  public listenTo(): string | Function {
    return MyChildEntity;
  }

  public async afterUpdate(event: LoadEvent<MyChildEntity>) {
    console.log('It works! The event is triggered as expected!');

    const builder = event.connection
      .createQueryBuilder()
      .delete()
      .from(MyChildEntity)
      .where('"myEntityId" IS NULL');

    return builder.execute();
  }
}

Однако при выполнении вышеуказанного запроса обновление еще не запускалось, поэтому из базы данных ничего не удаляется. Я ожидал, что удаление удалит потерянные строки.

Согласно журналам TypeORM запросы выполняются в следующем порядке:

START TRANSACTION
UPDATE "my_children_table" SET "myEntityId" = $2 WHERE "id" = $1 -- PARAMETERS: [2,null]
DELETE FROM "my_children_table" WHERE "myEntityId" IS NULL
COMMIT

Если я запускаю ту же транзакцию непосредственно в моей базе данных (Я использую PostgreSQL), все работает, как ожидалось, но TypeORM ведет себя так, как DELETE выполнялся до UPDATE.

Не могли бы вы помочь мне понять, что я делаю не так?

1 Ответ

0 голосов
/ 14 июля 2020

Я решил это, зафиксировав текущую транзакцию (чтобы данные были сохранены в базе данных) и запустив новую транзакцию, поэтому TypeORM зафиксирует эту новую транзакцию позже. Я вернул выполнение своего запроса (обещание), чтобы гарантировать, что TypeORM будет его ждать:

public async afterUpdate(event: LoadEvent<MyChildEntity>) {
  await event.queryRunner.commitTransaction();
  await event.queryRunner.startTransaction();
  return event.manager
    .createQueryBuilder()
    .delete()
    .from(MyChildEntity)
    .where('"myEntityId" IS NULL')
    .execute();
}
...