Wel*_*elp 5 javascript typescript typeorm nestjs
我想要的是每当创建新旅行时,该room列都应该填充${tripId}_${someRandomStringHere}. 例如,我刚刚使用这个主体创建了一个新的旅行:
新创建的trip具有. 因此,响应的值再次为:。id15room15_4gupvdo0ea408c25ia0qsbh${tripId}_${someRandomStringHere}
每当我请求并创建行程时,这都会按预期工作。但是每当我查询创建的所有行程时,每个行程对象的属性都会显示!POSTroomnull
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
}
Run Code Online (Sandbox Code Playgroud)
我的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
}
Run Code Online (Sandbox Code Playgroud)
我不认为我需要包含代码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)
}
}
Run Code Online (Sandbox Code Playgroud)
起初它不起作用,但在再次挖掘了几个小时后,我需要添加一个subscriber具有订阅者路径值的属性才能使其ormconfig.json工作!例如:"subscribers": [
"src/subscriber/*.ts"
]
同样,Trip Subscriber代码对我来说就像意大利面条,因为我已经拥有该event.entity对象,但我不知道如何更新它,而不需要使用event.manager.getRepository(). 请问有人可以帮我修复这个代码吗?正确的做法是什么?
我的问题是:
我来自 Rails。因此,必须创建文件/订阅者才能做到这一点有点累。与 ActiveRecord 的after_save回调不同,它非常简单。
附言。我是 Nest-js 和 typeorm 的新手
小智 6
@AfterInsert方法将在插入数据库完成后修改您的 JS 对象。这就是您的代码无法正常工作的原因。你必须使用@BeforeInsert装饰器。BeforeInsert将在插入/保存到数据库之前修改您的 JS 实体/对象。
您的情况似乎是AfterInsert,您正在创建随机房间字符串,但您没有将该值保存到数据库中,仅使用 id 的返回值以便您可以创建该字符串。您可以在您中做的AfterInsert是再次运行该save()函数EntityManager并将RepositoryManger值提交到数据库,类似于您在您中发生的情况Subscriber。我还没有深入研究Subscriber/ ListenervsBefore-/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)
Run Code Online (Sandbox Code Playgroud)
它看起来有点笨重,但它不需要对数据库进行两次写入(尽管您肯定需要确保创建后 room 和 trip 具有相同的 id)。
最后一个选择是在数据库中创建一个触发器,它与 JavaScript 代码执行相同的操作。
| 归档时间: |
|
| 查看次数: |
17149 次 |
| 最近记录: |