TypeORM子关系查询指定列报EntityPropertyNotFoundError
TypeORM关联查询指定关联字段报错问题
问题场景
定义了Order和User两个TypeORM实体,实体定义代码如下:
Order实体
@Entity('orders') export class Order { @PrimaryGeneratedColumn() id: number; @Column('enum', {enum: OrderStatus, default: OrderStatus.NEW}) status: OrderStatus @Column('float') amount: number @Column('float') fees: number @ManyToOne(() => User, (user) => user.orders) user: User; @OneToMany(() => OrderToProduct, orderToProduct => orderToProduct.order, { cascade: true, }) products: OrderToProduct[] @CreateDateColumn() createdAt: Date = new Date(); @UpdateDateColumn() updatedAt: Date; }
User实体
@Entity('users') export class User { @PrimaryGeneratedColumn() id: number; @Column({length: 255}) name: string; @Column({length: 255, unique: true}) email: string; @Column({length: 255}) password: string; @CreateDateColumn() createdAt: Date = new Date(); @OneToMany(() => Order, (order) => order.user) orders: Order[]; @UpdateDateColumn() updatedAt: Date; @OneToMany(() => Product, (product) => product.user) products: Product[] }
需求为查询订单数据时,仅关联返回所属用户的id、name字段,最初尝试的查询代码如下:
this.orderRepository.find({ relations: { user: { id: true, name: true } }, where: { user: { id: user.id } } })
代码执行后抛出错误:
EntityPropertyNotFoundError: Property "id" was not found in "User". Make sure your query is correct.
如果将关联配置改为直接加载完整user关联对象,代码如下,则查询可正常运行:
relations: { user: true },
报错原因
报错本质是对TypeORM find方法配置项的作用理解错误:
relations配置项的作用是声明需要加载的关联关系,配置树的所有键必须对应实体上定义的关联属性(即被@ManyToOne/@OneToMany/@OneToOne/ManyToMany装饰的属性),普通数据库字段不能写在这个配置下。在user嵌套下写id: true、name: true时,TypeORM会把id、name识别为User实体下挂载的子关联,自然找不到对应属性,直接抛出属性不存在的错误。- 配置
user: true时,仅声明要加载Order下的user关联,默认会查询User实体的所有普通字段,因此不会触发报错。
解决方案
要实现关联实体仅返回指定字段,需要搭配select配置项声明要返回的字段(包含主表字段和关联表字段),不能在relations中写字段选择规则,正确写法如下:
this.orderRepository.find({ // 声明要加载user关联 relations: { user: true }, // 在select中指定所有需要返回的字段,包括关联表的目标字段 select: { id: true, status: true, amount: true, fees: true, createdAt: true, user: { id: true, name: true } }, where: { user: { id: user.id } } })
其他实现方式
也可以使用QueryBuilder实现相同效果,字段控制更灵活:
this.orderRepository.createQueryBuilder('order') .leftJoin('order.user', 'user') .addSelect(['user.id', 'user.name']) .where('user.id = :userId', { userId: user.id }) .getMany()
注意事项
- 关联实体的字段选择必须写在
select配置对应关联名的嵌套对象中,不能写入relations配置 - 指定关联字段返回时,必须包含关联的主键字段(即User的id),否则TypeORM无法完成关联实体的映射,会返回null值
内容的提问来源于stack exchange,提问作者Joseph
相关产品推荐
相关产品推荐

