You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在TypeORM中基于多列及特定值建立ManyToOne关联

解决方案

方案1:单表继承拆分实体(推荐,符合TypeORM最佳实践)

利用TypeORM的单表继承特性,按type字段把listvalues表拆分为两个子实体,关联时直接对应特定类型的记录:

// 基础实体,对应listvalues表
@Entity('listvalues')
@TableInheritance({ column: { type: 'varchar', name: 'type' } })
export class ListValueSchema extends SomeValue {
  @PrimaryGeneratedColumn({ type: 'bigint' })
  ID: number;

  @Column()
  subId: number;

  @Column()
  value: string;
}

// 对应type='city'的记录
@ChildEntity('city')
export class CityValueSchema extends ListValueSchema {}

// 对应type='country'的记录
@ChildEntity('country')
export class CountryValueSchema extends ListValueSchema {}

// 修改后的Address实体
@Entity('addresses')
export class AddressSchema extends SomeValue {
  @PrimaryGeneratedColumn({ type: 'bigint' })
  ID: number;

  @ManyToOne(() => CountryValueSchema)
  @JoinColumn({ name: 'country' })
  country: CountryValueSchema;

  @ManyToOne(() => CityValueSchema)
  @JoinColumn({ name: 'city' })
  city: CityValueSchema;

  @Column()
  street: string;
}

这种方式会自动在查询时添加type字段的过滤条件,无需额外配置。

方案2:关联时指定where条件

如果不想拆分实体,可直接在@ManyToOne的选项中添加where参数,强制关联特定type的记录:

@Entity('listvalues')
export class ListValueSchema extends SomeValue {
  @PrimaryGeneratedColumn({ type: 'bigint' })
  ID: number;

  @Column()
  subId: number;

  @Column()
  type: string;

  @Column()
  value: string;
}

@Entity('addresses')
export class AddressSchema extends SomeValue {
  @PrimaryGeneratedColumn({ type: 'bigint' })
  ID: number;

  @ManyToOne(() => ListValueSchema, {
    where: { type: 'country' }
  })
  @JoinColumn({ name: 'country' })
  country: ListValueSchema;

  @ManyToOne(() => ListValueSchema, {
    where: { type: 'city' }
  })
  @JoinColumn({ name: 'city' })
  city: ListValueSchema;

  @Column()
  street: string;
}

注意:这种方式不会自动校验保存时关联记录的type是否符合要求,需要在业务逻辑中自行验证。

方案3:基于数据库视图关联

针对复杂过滤场景,可给listvalues表创建对应类型的视图,再为视图创建实体关联:

  1. 创建视图(SQL示例):
CREATE VIEW city_values AS
SELECT ID, subId, value FROM listvalues WHERE type = 'city';

CREATE VIEW country_values AS
SELECT ID, subId, value FROM listvalues WHERE type = 'country';
  1. 视图对应的实体:
@ViewEntity({ name: 'city_values' })
export class CityValueView extends SomeValue {
  @PrimaryColumn({ type: 'bigint' })
  ID: number;

  @Column()
  subId: number;

  @Column()
  value: string;
}

@ViewEntity({ name: 'country_values' })
export class CountryValueView extends SomeValue {
  @PrimaryColumn({ type: 'bigint' })
  ID: number;

  @Column()
  subId: number;

  @Column()
  value: string;
}

// Address实体关联视图
@Entity('addresses')
export class AddressSchema extends SomeValue {
  @PrimaryGeneratedColumn({ type: 'bigint' })
  ID: number;

  @ManyToOne(() => CountryValueView)
  @JoinColumn({ name: 'country' })
  country: CountryValueView;

  @ManyToOne(() => CityValueView)
  @JoinColumn({ name: 'city' })
  city: CityValueView;

  @Column()
  street: string;
}

该方式适合只读场景,无法通过视图实体修改原始表数据。


内容的提问来源于stack exchange,提问作者Schuere

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 18:18:31