Skip to content

关系模型定义

image.png

多对一/一对多 **

@ManyToOne@OneToMany 成对出现,例如一个实体拥有多条日志,而多条日志属于一个实体。 第一个参数返回对应的表的目标实体,第二个参数指定对应表的对应字段名。由于指定了对应实体,这里可以推导出类型。 注解内容:user:

ts
@Entity()
export class User {
  @PrimaryGeneratedColumn()
  id: number;

  @Column()
  username: string;

  @Column()
  password: string;

  // OneToMany 定义:一个用户对应多个日志记录
  @OneToMany(() => Logs, (logs) => logs.user) 
  logs: Logs[]; // 一个用户拥有多个日志数据,在数据库中被解释为外键
}

logs:

ts
// logs.entity.ts
import { Entity, PrimaryGeneratedColumn, Column, ManyToOne } from 'typeorm';
import { User } from './user.entity';

@Entity()
export class Logs {
  @PrimaryGeneratedColumn()
  id: number;

  @Column()
  path: string;

  @Column()
  method: string;

  @Column()
  data: string;

  @ManyToOne(() => User, (user) => user.logs)
  @JoinColumn({name:'userwaijian'}) // 也可指定外键列名,默认为 userId
  user: User; // 每个日志被唯一的用户拥有,通过外键引用
}

多对多

对应 useruser_roles

ts
@ManyToMany(() => User, (user) => user.roles)
users: User[];

@ManyToMany(() => Role, (role) => role.users)
@JoinTable() // 使用 JoinTable 来创建联接表
roles: Role[];

从已有数据库生成 typeORM 实体类

https://www.npmjs.com/package/typeorm-model-generator

CRUD 操作

简单操作可以写在 controller 层,复杂操作则在 service 层。

依赖注入 (DI) 容器

将对象的创建和依赖关系的管理交给外部容器管理,而非直接手动实例化对象。通过构造函数、属性或方法注入依赖。 注册提供者(Provider) 可以被注入的类需要注册为提供者 provider,由 @Injectable() 标记,并且在模块的 providers 数组中注册。 注入依赖 主要通过构造函数注入

ts
constructor(private readonly userService: UserService) {}

image.png

image.png

步骤

  • 数据访问层:在根模块上导入 typeORM
ts
@Module({
  imports: [
    TypeOrmModule.forRootAsync({
      imports: [ConfigModule],
      inject: [ConfigService],
      useFactory: (configService: ConfigService) => {
        console.log("config:", configService);
        console.log('开始配置数据库连接'); 
        const dbConfig = {
          type: configService.get('TYPEORM_TYPE'), 
          host: configService.get('TYPEORM_HOST'),
          port: configService.get('TYPEORM_PORT'),
          username: configService.get('TYPEORM_USERNAME'),
          password: configService.get('TYPEORM_PASSWORD'),
          database: configService.get('TYPEORM_DATABASE'),
          synchronize: true,
          entities: [User,Profile,Logs,Roles], // 实体类数组
          logging: ['error'],
        } as TypeOrmModuleOptions;
        console.log('数据库配置完成:', dbConfig);
        return dbConfig;
      },
    }),
  ],
  controllers: [],
  providers: [],
})
  • 设置实体类 entity
  • 业务逻辑层:CRUD 方法
ts
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { User } from './user.entity';
import { Repository } from 'typeorm';
// 逻辑层
@Injectable()
export class UserService {
  constructor(
    @InjectRepository(User) private readonly userRepository: Repository<User>,
  ) {} // 注入 User 实体对应的 Repository

  async getAll() {
    const res = await this.userRepository.find({});
    console.log('database res:', res);
    return res;
  }

  async findOne(username: string) {
    const res = await this.userRepository.findOne({ where: { username } });
    return res;
  }

  async create(user: User) {
    const user_temp = await this.userRepository.create(user); // user属性key与对应的user表一致
    return this.userRepository.save(user_temp);
  }
// 根据传入的字段创建一个实体对象。这个对象是一个临时的 JavaScript 实例,用于表示数据库中的一行数据。然后再用save
// 做持久化

  async update(id: number, user: Partial<User>) {
    await this.userRepository.update(id, user);
  }

  async remove(id: number) {
    await this.userRepository.delete(id);
  }
}
  • 路由层:
ts
Controller('user')
export class UserController {
  constructor(
    private userService: UserService,
    private configService: ConfigService,
  ) {}

  @Get('getuser')
  getUsers() {
    return this.userService.getAll();
  }

  @Post('adduser')
  addUser(){
    const user = {
      username: 'test2',
      password: 'test'
    } as User;
    return this.userService.create(user); 
  }
}

ORM 操作外键反向关系

先从返向关系对应的表里 find 出对应的记录,成为一个 ORM 对象,再去操作这个 ORM 对象:

ts
@Post('addlog')
async addLog() {
  const users: User[] = [await this.userService.getUserById(1) as User, await this.userService.getUserById(2) as User];
  let logs: Logs[] = [{
    id: 1,
    path: '/api/v1/user',
    method: 'GET',
    data: '',
    result: 200,
    userId: users[0]
  }];
  return this.userService.addLog(logs[0]);
}

联合查询