TypeORM 一对一(One-To-One)关联子表未生成外键问题求助
问题原因
- 异步方法未加await:
contactRepository.save()和userRepository.save()都是异步方法,你没有加await关键字,不仅保存顺序不可控,甚至可能在事务未提交时就结束流程。
- 异步方法未加await:
- 双向关系未手动关联反向侧:TypeORM不会自动维护双向关联的两侧,你只给
user.contacts赋值了,但是没有给contacts.user_id赋值,所以联系人表的user_id字段没有值。
- 双向关系未手动关联反向侧:TypeORM不会自动维护双向关联的两侧,你只给
- 外键归属不符合预期:
@JoinColumn注解标记的是关系的拥有方,外键会存在拥有方对应的表中。你现在把@JoinColumn加在Users实体上,所以外键contact_id默认存在users表,如果你希望user_contacts表存user_id外键,需要调整@JoinColumn的位置。
- 外键归属不符合预期:
修复方案
方案1:调整外键归属到UserContacts侧(推荐,符合你预期的user_contacts表存user_id的需求)
第一步:修改实体定义
// Users 实体去掉@JoinColumn,作为关系的反向侧 @Entity() export class Users { @PrimaryGeneratedColumn() user_id: number; // 新增cascade: true开启级联保存,不需要单独存联系人 @OneToOne(_ => UserContacts, contact => contact.user_id, { cascade: true }) contacts: UserContacts } // UserContacts 实体添加@JoinColumn,作为关系拥有方,外键存在该表 @Entity() export class UserContacts { @PrimaryGeneratedColumn() contact_id: number; @OneToOne(_ => Users, users => users.contacts) @JoinColumn({ name: 'user_id' }) // 指定外键字段名 user_id: Users; }
第二步:修改保存逻辑
async function bootstrap() { try { const connection = await createConnection(); const userRepository = connection.getRepository(Users); const contacts = createContacts(); const user = createUser(contacts); // 手动关联双向关系的另一侧 contacts.user_id = user; // 因为开了级联,保存用户会自动保存关联的联系人 await userRepository.save(user); console.info('Done!'); } catch (e) { console.error(e.message); } }
方案2:不调整外键归属,手动补全关联
如果你希望保留users表存contact_id的设计,又需要user_contacts表的user_id有值,只需要修改保存逻辑,补全反向关联和await即可:
async function bootstrap() { try { const connection = await createConnection(); const userRepository = connection.getRepository(Users); const contactRepository = connection.getRepository(UserContacts); const contacts = createContacts(); // 先保存联系人拿到contact_id await contactRepository.save(contacts); const user = createUser(contacts); // 保存用户拿到user_id await userRepository.save(user); // 手动给联系人关联用户后再更新联系人 contacts.user_id = user; await contactRepository.save(contacts); console.info('Done!'); } catch (e) { console.error(e.message); } }
内容的提问来源于stack exchange,提问作者Igor Doroshenko
相关产品推荐
相关产品推荐

