TypeORM批量插入含外键实体:如何解决user.id为空报错
解决TypeORM创建关联User和Post时user.id为空的问题
问题原因
你现在的代码逻辑有两个核心问题:
User.create()只是在内存中创建实体对象,还没插入数据库,所以user.id自然是空的,这时候给Post的userId赋值肯定会报错。- 代码里
Post.create({...}).save()已经会执行插入操作,后面又调用await Post.insert(post)属于重复操作,而且插入顺序搞反了——必须先把User插入数据库拿到ID,再创建关联的Post。
解决方案(无需修改实体表)
方案1:先插入User获取ID,再插入Post
这是最直接的方式,先通过User.insert拿到插入后的用户ID,再用这个ID创建Post:
// 插入User并获取返回的ID const userInsertResult = await User.insert({ name: 'bobby' }); const userId = userInsertResult.identifiers[0].id; // 用拿到的userId插入Post await Post.insert({ title: 'test', userId: userId });
如果你的ID是自增主键,insert方法返回的identifiers数组里会包含刚插入的记录ID。
方案2:利用TypeORM的关联映射自动处理(推荐)
如果你的User和Post实体已经配置了关联关系(比如User是OneToMany,Post是ManyToOne),可以直接通过关联属性关联两个实体,让TypeORM自动帮你处理外键:
假设你的实体配置大概是这样:
// User实体 @Entity() export class User { @PrimaryGeneratedColumn() id: number; @Column() name: string; @OneToMany(() => Post, post => post.user) posts: Post[]; } // Post实体 @Entity() export class Post { @PrimaryGeneratedColumn() id: number; @Column() title: string; @ManyToOne(() => User, user => user.posts) user: User; }
那创建代码可以简化成:
const user = User.create({ name: 'bobby', posts: [Post.create({ title: 'test' })] }); // 保存User的时候,TypeORM会自动插入User,然后插入关联的Post并设置正确的userId await User.save(user);
这种方式不用手动处理ID,TypeORM会自动维护关联关系,代码更简洁。
方案3:修正你原来的代码逻辑
如果你想保留类似原来的create写法,记得先保存User拿到ID,再创建并保存Post,不要混用save和insert:
const user = User.create({ name: 'bobby' }); // 先保存User到数据库,此时user.id会被赋值 await user.save(); const post = Post.create({ title: 'test', userId: user.id }); await post.save();
这其实就是你最开始的正确写法,只是后来改成insert时逻辑出现了错误。
内容的提问来源于stack exchange,提问作者jmecs
相关产品推荐
相关产品推荐

