我想要的是无论何时创建新的旅程,都应在room
列中填充${tripId}_${someRandomStringHere}
。因此,例如,我刚刚使用此主体创建了一个新行程:
新创建的trip
的{{1}}中的id
。因此,响应中的15
的值为room
,因为同样:15_4gupvdo0ea408c25ia0qsbh
。
每当我${tripId}_${someRandomStringHere}
请求并创建行程时,此操作就会按预期的方式工作。 但是,每当我查询所有创建的行程时,每个行程对象的POST
属性都会显示room
!
null
Look at the /api/trips:
属性为 NULL 。所以我到底不知道发生了什么事。
我的room
代码是:
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
}
代码,但无论如何..
我不知道为什么会这样,因为我的用户实体带有@BeforeUpdate并且可以正常工作...
在阅读了许多类似的github问题之后,观看了youtube教程[嗨,本·阿瓦德! :D],通过使用订阅服务器
,我发现了一个解决方法。实际上,我不知道侦听器/订阅者有什么区别。也许我做错了用法。有人可以启发我吗?例如,实体侦听器的AfterSave与实体订阅者的AfterSave的区别。什么时候/最好用?这样的事情。无论如何都回到Trip Controller
我创建了一个"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
查询和更新它。请有人可以为我修复此代码吗?正确的方法呢?
我的问题是:
我来自Rails。因此,必须创建文件/订户才能使其有些累。与ActiveRecord的event.manager.getRepository()
回调不同,它非常简单。
PS。我是Nest-js和Typeorm的新手
答案 0 :(得分:1)
您的AfterInsert
所发生的情况是您正在创建随机房间字符串就很好了,但是您没有将值保存到数据库中,仅使用了ID的返回值,以便您可以创建字符串。您可以在AfterInsert
中执行的操作再次从save()
或EntityManager
运行RepositoryManger
函数,并将值提交给数据库,类似于您在数据库中发生的情况您Subscriber
。我还没有深入研究Subscriber
/ Listener
和Before-/AfterInsert
装饰器,因此无法对您的问题给出更深层次的答案。
如果您不想对数据库进行两次提交,则始终可以查询最新的id并将其递增1(因此,与新对象id 匹配) ),例如
const maxId = await this.tripRepository.findOne({select: ['id'], order: {id: "DESC"} });
const trip = await this.tripRepository.create(data);
const randomString = Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15)
this.room = `${maxId + 1}_${randomString}`
trip.driver = driver
await this.tripRepository.save(trip)
看起来有点笨拙,但是不需要两次写入数据库(尽管您肯定需要确保创建后的房间和旅程具有相同的ID)。
您最后的选择是在数据库中创建一个与JavaScript代码相同的触发器。
答案 1 :(得分:0)
@AfterInsert
方法仅会在插入数据库后修改您的JS对象。因此,这就是为什么您的代码无法正常工作的原因。您必须使用@BeforeInsert
装饰器。 BeforeInsert
将在插入/保存到数据库之前修改您的JS实体/对象。
答案 2 :(得分:0)
您只需要在createSocketRoom()函数中使用“ this.save()”