TypeORM AfterSave() 在创建后触发,但在查询时返回 NULL

新手上路,请多包涵

我有一个名为 Trip 的实体。结构是: 数据库结构

我想要的是每当创建新行程时, room 列应该填充 ${tripId}_${someRandomStringHere} 。因此,例如,我刚刚使用此主体创建了一个新行程:

旅行体

响应应该是: 行程响应

新创建的 trip 具有 id15 。因此,响应的 room 的值为 15_4gupvdo0ea408c25ia0qsbh 因为再次: ${tripId}_${someRandomStringHere}

每当我 POST 请求并创建行程时,这都会按 预期 工作。 但是 每当我查询创建的所有行程时,每个行程对象的 room 属性都会显示 null

Look at the /api/trips:

旅行数组

room 属性为 NULL 。所以到底是什么我不明白发生了什么。

我的 Trip Entity 代码是:

 import { PrimaryGeneratedColumn, Column, CreateDateColumn,
UpdateDateColumn, Entity, Unique, ManyToOne, AfterInsert, JoinColumn, getConnection } from 'typeorm'
import { DriverEntity } from 'src/driver/driver.entity';

@Entity('trips')
export class TripEntity {
  @PrimaryGeneratedColumn()
  id: number

  @Column()
  destination: string

  @Column('decimal')
  destination_lat: number

  @Column('decimal')
  destination_long: number

  @Column()
  maxPassenger: number

  @Column()
  totalPassenger: number

  @Column({ nullable: true })
  room: string

  @CreateDateColumn()
  created_at: Date

  @UpdateDateColumn()
  updated_at: Date
// --------->HERE: The after insert
  @AfterInsert()
  async createSocketRoom(): Promise<void> {
    const randomString = Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15)
    this.room =  `${this.id}_${randomString}`
  }

  // Trip belongs to driver
  // Adds driver_id to trips table
  @ManyToOne(type => DriverEntity, driver => driver.trips)
  @JoinColumn({ name: 'driver_id' })
  driver: DriverEntity
}

我的 Trip Service Code 是:

 async create(data: CreateTripDTO) {
    const { driver_id } = data
    const driver = await this.driverRepository.findOne({ where: { id: driver_id } })
    const trip = await this.tripRepository.create(data)
    trip.driver = driver

    await this.tripRepository.save(trip)
    return trip
  }

我不认为我需要包含 Trip Controller 代码但无论如何..我不知道为什么会这样,因为我的用户实体带有 @BeforeUpdate 并且工作正常……

在阅读了很多类似的 github 问题之后,观看了 youtube 教程 [Hi Ben Awad! :D], 我找到了一些修复.. 通过使用订阅者

其实我不知道Listener/Subscriber有什么区别。也许我用错了。有人可以启发我吗?例如,实体监听器的 AfterSave 与实体订阅者的 AfterSave 的区别。何时/最佳情况下使用?类似的东西。无论如何回到 "fix..."

我创建了一个 Trip Subscriber

 import { EventSubscriber, EntitySubscriberInterface, InsertEvent } from "typeorm";
import { TripEntity } from "src/trip/trip.entity";

@EventSubscriber()
export class TripSubsriber implements EntitySubscriberInterface<TripEntity> {
    // Denotes that this subscriber only listens to Trip Entity
    listenTo() {
      return TripEntity
    }

    // Called after entity insertion
    async afterInsert(event: InsertEvent<any>) {
        console.log(`AFTER ENTITY INSERTED: `, event.entity);
        const randomString = Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15)
        // query the trip with given event.entity
        const trip = await event.manager.getRepository(TripEntity).findOne(event.entity.id)
        // populate the room with desired format
        trip.room = `${trip.id}_${randomString}`
        // save it!
        await event.manager.getRepository(TripEntity).save(trip)
    }

}

起初它不起作用,但再次挖掘了几个小时后,我需要添加一个 subscriber 属性,其值为我的订户在 ormconfig.json 的路径值才能正常工作!例如: "subscribers": [ "src/subscriber/*.ts" ]

同样, Trip Subscriber 代码对我来说似乎是意大利面条,因为我已经有了 event.entity 对象,但我不知道如何更新它而无需使用 event.manager.getRepository() 。请有人可以为我修复此代码吗?正确的做法是什么?

现在,它正在工作! 请求正文: 请求体

/api/trips 资源: 资源

我的问题是:

  1. 为什么每当我使用那个方法 method subscriber 时,它都不起作用。这不是正确的方法吗?为什么它在文档中?还是用于其他用例?
  2. 我真的必须使用订户才能实现吗?这么多步骤。

我来自 Rails。所以必须创建文件/订阅者才能做到这一点有点累人。与 ActiveRecord 的 after_save 回调不同,它非常容易..

附言。我是 nest-js 和 typeorm 的新手

原文由 Welp 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 937
1 个回答

@AfterInsert 方法将在插入数据库完成后修改您的 JS 对象。这就是为什么您的代码不起作用的原因。你必须使用 @BeforeInsert 装饰器。 BeforeInsert 将在插入/保存到数据库之前修改您的 JS 实体/对象。

原文由 vlapo21 发布,翻译遵循 CC BY-SA 4.0 许可协议

推荐问题