TypeORM:为何@ManyToOne反向关联在实体save后未被水合?
问题原因与解决方案
为什么a.bs输出0?
TypeORM的双向关联(反向映射)只是用来建立数据库层面的关联关系,以及支持从关联实体发起查询/级联操作,但不会自动将数据库中新增的关联数据同步到已经加载到内存中的实体对象里。你保存完3个B实例后,内存中的a还是最初保存时的状态(bs为空数组),没有从数据库重新拉取关联数据,所以输出0。
维护数据库与模型一致性的正确方式
1. 手动维护内存中的关联关系
在保存B实例后,手动将其添加到a.bs数组中,这样内存中的a对象就能实时反映关联状态:
AppDataSource.initialize().then(async () => { const a = await AppDataSource.manager.save(new A([])) const b1 = await AppDataSource.manager.save(new B(a)) a.bs.push(b1) const b2 = await AppDataSource.manager.save(new B(a)) a.bs.push(b2) const b3 = await AppDataSource.manager.save(new B(a)) a.bs.push(b3) console.log(a.bs.length) // 输出3 }).catch(error => console.log(error))
2. 重新从数据库加载A实体并关联查询
保存完所有B后,重新查询A并显式加载关联的bs,这样能获取到最新的数据库状态:
AppDataSource.initialize().then(async () => { const a = await AppDataSource.manager.save(new A([])) await AppDataSource.manager.save(new B(a)) await AppDataSource.manager.save(new B(a)) await AppDataSource.manager.save(new B(a)) // 重新查询A,同时加载关联的bs const freshA = await AppDataSource.manager.findOne(A, { where: { id: a.id }, relations: ["bs"] }) console.log(freshA?.bs.length) // 输出3 }).catch(error => console.log(error))
3. 使用级联保存自动维护关联
修改A实体的@OneToMany装饰器,添加级联配置,这样保存A时会自动保存关联的B,同时维护内存中的关联状态:
首先修改A实体:
@Entity() export class A { @PrimaryGeneratedColumn() id!: number // 添加cascade配置,支持插入级联 @OneToMany(() => B, (b) => b.a, { cascade: ["insert"] }) bs: B[] constructor(bs: B[]) { this.bs = bs } }
然后修改执行代码:
AppDataSource.initialize().then(async () => { const a = new A([]) // 先把B实例添加到a.bs中 a.bs.push(new B(a)) a.bs.push(new B(a)) a.bs.push(new B(a)) // 保存a时自动级联保存所有关联的B await AppDataSource.manager.save(a) console.log(a.bs.length) // 输出3 }).catch(error => console.log(error))
内容的提问来源于stack exchange,提问作者Dinu
相关产品推荐
相关产品推荐

