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

TypeORM中定义带关联关系的实体时使用抽象类的相关问题

TypeORM中定义带关联关系的实体时使用抽象类的相关问题

看起来你现在有两个关联的TypeORM实体(BookEntity和BookContentEntity),里面重复了不少审计类字段(比如id、createdAt这些),想要用抽象类来复用这些公共逻辑对吧?我来帮你梳理下怎么实现,同时保证关联关系正常工作。

先贴出你提供的原始实体代码(整理后):

// BookEntity 原始代码
import { BookContentEntity } from '@src/modules/book/entities/book-content.entity';
import {
  Column,
  CreateDateColumn,
  DeleteDateColumn,
  Entity,
  OneToMany,
  PrimaryGeneratedColumn,
  UpdateDateColumn
} from 'typeorm';

@Entity()
export class BookEntity {
  @PrimaryGeneratedColumn('uuid')
  id: string;

  @CreateDateColumn()
  createdAt: Date;

  @UpdateDateColumn()
  updatedAt: Date;

  @DeleteDateColumn()
  deletedAt: Date;

  @Column()
  name: string;

  @Column({ unique: true, default: null })
  slug: string;

  @Column({ default: null })
  description: string;

  @OneToMany(() => BookContentEntity, (content) => content.book, { cascade: ['soft-remove'] })
  content: Array<BookContentEntity>;

  constructor(partial: Partial<BookEntity>) {
    Object.assign(this, partial);
  }
}
// BookContentEntity 原始片段
import { BookContentType } from '@src/core/enums/book-content-type.enum';
import { BookEntity } from '@src/mod...

优化方案:用抽象类封装公共字段

我们可以把重复的审计字段、基础构造逻辑抽成一个抽象基类,让所有实体继承它,这样既能减少重复代码,也不影响关联关系的配置:

1. 创建抽象基类

import {
  PrimaryGeneratedColumn,
  CreateDateColumn,
  UpdateDateColumn,
  DeleteDateColumn,
} from 'typeorm';

// 抽象基类:封装所有实体的公共审计字段和基础构造逻辑
export abstract class BaseEntity {
  @PrimaryGeneratedColumn('uuid')
  id: string;

  @CreateDateColumn()
  createdAt: Date;

  @UpdateDateColumn()
  updatedAt: Date;

  @DeleteDateColumn()
  deletedAt: Date;

  constructor(partial: Partial<BaseEntity>) {
    Object.assign(this, partial);
  }
}

2. 修改BookEntity继承基类

import { Column, Entity, OneToMany } from 'typeorm';
import { BaseEntity } from './base.entity'; // 引入抽象基类
import { BookContentEntity } from '@src/modules/book/entities/book-content.entity';

@Entity()
export class BookEntity extends BaseEntity {
  @Column()
  name: string;

  @Column({ unique: true, default: null })
  slug: string;

  @Column({ default: null })
  description: string;

  // 关联关系写法完全不变,和之前的逻辑一致
  @OneToMany(() => BookContentEntity, (content) => content.book, { cascade: ['soft-remove'] })
  content: Array<BookContentEntity>;

  constructor(partial: Partial<BookEntity>) {
    super(partial); // 调用基类构造函数,保证公共字段的赋值逻辑生效
  }
}

3. 补全并修改BookContentEntity继承基类

import { Column, Entity, ManyToOne } from 'typeorm';
import { BaseEntity } from './base.entity';
import { BookEntity } from '@src/modules/book/entities/book.entity';
import { BookContentType } from '@src/core/enums/book-content-type.enum';

@Entity()
export class BookContentEntity extends BaseEntity {
  @Column({ type: 'enum', enum: BookContentType })
  type: BookContentType;

  // 示例字段:根据你的实际业务需求调整
  @Column({ default: '' })
  contentText: string;

  @Column({ default: 0 })
  sortOrder: number;

  // 关联关系写法同样不受影响
  @ManyToOne(() => BookEntity, (book) => book.content)
  book: BookEntity;

  constructor(partial: Partial<BookContentEntity>) {
    super(partial);
  }
}

关键注意事项

  • 抽象基类不需要加@Entity装饰器,TypeORM会自动识别继承它的实体类
  • 实体间的关联关系(OneToMany/ManyToOne等)配置完全不受继承影响,写法和之前一致
  • 所有实体的构造函数必须调用super(partial),确保基类的公共字段赋值逻辑正常执行
  • 如果后续需要给所有实体添加公共字段(比如createdBy、updatedBy),直接在BaseEntity中添加即可,所有子类会自动继承

备注:内容来源于stack exchange,提问作者Korer

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.16 12:44:34