TypeORM如何不加载关联实体直接访问关联关系外键字段
问题背景
创建ManyToOne/OneToMany关联关系时,需要在对应字段上使用@ManyToOne/@OneToMany装饰器。
现有项目包含Project和Position两个实体,初始关联定义代码如下:
@Entity('positions') export class Position { @ManyToOne(() => Project, { nullable: false, eager: true, }) @JoinColumn() project: Project; }
按照TypeORM的关联实现逻辑,上述定义会在数据库自动生成projectId类型的外键列,存储关联的项目ID。默认访问实体的project属性时,TypeORM会自动根据projectId字段存储的ID,查询加载对应的完整Project关联实体。
核心问题
怎么在不触发关联实体加载的前提下,直接访问数据库里存的projectId字段值?
默认Position实体类上没有projectId属性,就算手动声明同名属性,也无法自动映射数据库中projectId列存储的值,以下测试写法无法生效:
@ManyToOne(() => Project, { nullable: false, eager: false, }) @JoinColumn() project: Project; projectId: string;
可行方案
分两种场景选择实现:
- 实体层固定映射(推荐,日常使用最方便)
在@JoinColumn装饰器里显式指定外键对应的数据库列名,同时单独声明projectId字段,用@Column装饰器做字段映射,保证两处的列名完全一致即可。
参考代码:
配置完成后,直接访问实例的@Entity('positions') export class Position { @ManyToOne(() => Project, { nullable: false, eager: false, // 关闭关联实体自动加载 }) @JoinColumn({ name: 'projectId' }) // 显式绑定外键列名 project: Project; @Column() // 映射数据库中同名字段 projectId: string; }projectId属性就能拿到外键值,不会触发额外的关联查询,只有主动访问project属性时,才会加载完整的Project实体。 - 查询层临时获取(无需修改实体定义)
如果不想修改实体结构,可以在查询时通过配置直接返回关联ID,不加载完整关联实体:
这种方式适合临时查询场景,不需要调整原有实体定义。// find查询配置 const positions = await positionRepository.find({ loadRelationIds: true, }); // 返回结果中project字段直接存储ID值,而非完整Project对象 // QueryBuilder写法 const positions = await positionRepository .createQueryBuilder('position') .loadRelationIdAndMap('position.projectId', 'position.project') .getMany();
注意:使用实体层映射方案时,不要给
projectId字段配置和外键约束冲突的更新、插入规则,否则会导致关联关系读写异常。
内容的提问来源于stack exchange,提问作者Timur Gilauri
相关产品推荐
相关产品推荐

