如何在NestJS+TypeORM中用关联表实现Item的可选Scale属性
实现方案(NestJS + TypeORM + PostgreSQL)
1. 定义Scale枚举
先创建TypeScript枚举,用枚举键作为scale_id存储值,枚举值作为显示用的名称:
// src/enums/scale.enum.ts export enum Scale { SCALE_1 = '小型', SCALE_2 = '中型', SCALE_3 = '大型', SCALE_4 = '超大' }
2. 创建ItemScale实体(对应item_scale表)
这个关联表存储Item与Scale的映射关系,设置联合主键并限制item_id唯一(确保一个Item最多对应一个Scale):
// src/entities/item-scale.entity.ts import { Entity, PrimaryColumn, ManyToOne, JoinColumn } from 'typeorm'; import { Item } from './item.entity'; import { Scale } from '../enums/scale.enum'; @Entity('item_scale') export class ItemScale { @PrimaryColumn({ type: 'enum', enum: Scale }) scale_id: Scale; @PrimaryColumn({ unique: true }) item_id: number; @ManyToOne(() => Item, (item) => item.scale, { onDelete: 'CASCADE' }) @JoinColumn({ name: 'item_id' }) item: Item; }
3. 修改Item实体,关联ItemScale
在Item实体中添加一对一关联,标记为可选(nullable: true):
// src/entities/item.entity.ts import { Entity, PrimaryGeneratedColumn, Column, OneToOne, JoinColumn } from 'typeorm'; import { ItemScale } from './item-scale.entity'; @Entity('item') export class Item { @PrimaryGeneratedColumn() id: number; // 你的现有属性 @Column() name: string; // ... 其他属性 @OneToOne(() => ItemScale, (itemScale) => itemScale.item, { nullable: true, cascade: true }) @JoinColumn({ name: 'id', referencedColumnName: 'item_id' }) scale: ItemScale; }
cascade: true可实现保存Item时自动同步关联的ItemScale数据。
4. 实现核心功能
4.1 通过scale_id查询Item
在Service层使用QueryBuilder关联查询:
// src/item/item.service.ts import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { Repository } from 'typeorm'; import { Item } from '../entities/item.entity'; import { Scale } from '../enums/scale.enum'; @Injectable() export class ItemService { constructor( @InjectRepository(Item) private itemRepository: Repository<Item>, ) {} async getItemsByScale(scaleId: Scale): Promise<Item[]> { return this.itemRepository .createQueryBuilder('item') .innerJoinAndSelect('item.scale', 'itemScale') .where('itemScale.scale_id = :scaleId', { scaleId }) .getMany(); } }
4.2 获取Scale名称
通过枚举直接映射存储的scale_id到显示名称:
// 示例:获取单个Item的Scale名称 const item = await this.itemRepository.findOne({ where: { id: 1 }, relations: ['scale'] }); const scaleName = item.scale ? Scale[item.scale.scale_id] : null;
5. 数据库枚举初始化(可选)
如果使用TypeORM自动同步(仅开发环境开启synchronize: true),会自动创建PostgreSQL枚举类型。若手动初始化,执行以下SQL:
CREATE TYPE scale_enum AS ENUM ('SCALE_1', 'SCALE_2', 'SCALE_3', 'SCALE_4');
内容的提问来源于stack exchange,提问作者sharf
相关产品推荐
相关产品推荐

