如何在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表创建对应类型的视图,再为视图创建实体关联:
- 创建视图(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';
- 视图对应的实体:
@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
相关产品推荐
相关产品推荐

