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

NestJS + TypeORM 实体数据库操作审计选型与实现疑问

NestJS 实体数据库操作审计方案:Listener vs Subscriber

一、Listener 实现(基于实体继承的公共审计类)

如果想通过实体继承复用审计逻辑,可以创建一个整合时间属性与审计钩子的抽象基类,需要审计的实体直接继承该类即可。

1. 创建带审计钩子的抽象基类

import { AfterInsert, BaseEntity } from 'typeorm';
import TimeProperty from './time-property';

// 整合时间属性与审计逻辑的抽象基类
export abstract class AuditableEntity extends TimeProperty {
  @AfterInsert()
  async handleAfterInsert() {
    // 编写插入后的审计逻辑,比如记录操作日志、关联操作用户等
    console.log(`实体 ${this.constructor.name} 已插入,ID:${(this as BaseEntity).id}`);
    // 示例:结合请求上下文获取当前用户(需自行实现请求上下文工具)
    // const currentUser = getCurrentUser();
    // this.createdBy = currentUser.id;
    // await this.save();
  }
}

2. 业务实体继承基类

需要审计的实体直接继承AuditableEntity,自动拥有时间字段与审计逻辑:

import { Entity, PrimaryGeneratedColumn, Column } from 'typeorm';
import { AuditableEntity } from './auditable-entity';

@Entity()
export class Product extends AuditableEntity {
  @PrimaryGeneratedColumn()
  id: number;

  @Column()
  name: string;

  // 自动继承created_time、updated_time字段,以及AfterInsert审计钩子
}

二、Subscriber 实现(单文件监听部分实体)

如果想集中管理审计逻辑,且仅监听继承TimeProperty的实体,可以创建一个全局Subscriber,在事件钩子中通过类型判断筛选目标实体。

1. 创建全局审计Subscriber

import {
  EntitySubscriberInterface,
  EventSubscriber,
  InsertEvent,
  UpdateEvent,
  DeleteEvent,
} from 'typeorm';
import TimeProperty from './time-property';

@EventSubscriber()
export class AuditSubscriber implements EntitySubscriberInterface {
  // 监听所有实体,后续通过类型判断过滤目标
  listenTo() {
    return Object;
  }

  // 插入后审计
  async afterInsert(event: InsertEvent<any>) {
    if (event.entity instanceof TimeProperty) {
      console.log(`插入审计:${event.entity.constructor.name},ID:${event.entity.id}`);
      // 这里可添加具体审计操作,比如写入独立的审计日志表
    }
  }

  // 更新后审计
  async afterUpdate(event: UpdateEvent<any>) {
    if (event.entity instanceof TimeProperty) {
      console.log(`更新审计:${event.entity.constructor.name},ID:${event.entity.id}`);
    }
  }

  // 删除后审计
  async afterDelete(event: DeleteEvent<any>) {
    if (event.entity instanceof TimeProperty) {
      console.log(`删除审计:${event.entity.constructor.name},ID:${event.entity.id}`);
    }
  }
}

2. 注册Subscriber到NestJS

在app.module.ts中,将Subscriber配置到TypeOrmModule:

import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { AuditSubscriber } from './audit.subscriber';
import { Product } from './product.entity';

@Module({
  imports: [
    TypeOrmModule.forRoot({
      // 数据库连接配置
      type: 'postgres',
      host: 'localhost',
      port: 5432,
      username: 'postgres',
      password: 'password',
      database: 'test',
      entities: [Product],
      subscribers: [AuditSubscriber], // 注册全局审计Subscriber
      synchronize: true,
    }),
    TypeOrmModule.forFeature([Product]),
  ],
})
export class AppModule {}

方案选择建议

  • Listener:适合审计逻辑与实体强绑定、希望通过继承快速复用的场景,代码分散但实体层面更直观。
  • Subscriber:适合集中管理所有审计规则、无需修改实体代码的场景,便于统一调整审计策略。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 18:05:11