Nestjs教程如何使用TypeORM进行关系型数据库的操作与优化

在使用NestJS和TypeORM进行数据库操作时遇到几个问题想请教大家:

  1. 如何正确配置TypeORM与NestJS的关联?官方文档的示例不太清晰,特别是在异步加载数据库配置时容易报错
  2. 实体关系(一对一、一对多等)在TypeORM中的最佳实践是什么?比如外键设置和联级操作在实际项目中如何平衡性能与便利性?
  3. 针对复杂查询场景,TypeORM的QueryBuilder和原生SQL哪种方式更推荐?有没有性能对比的经验分享?
  4. 数据库连接池配置有哪些关键参数需要注意?尤其在微服务环境下如何避免连接泄漏?
  5. 迁移和种子数据的管理,有没有成熟的自动化方案推荐?
    最近在项目实践中踩了不少坑,希望有经验的朋友能分享一下实际解决方案。

3 回复

在NestJS中使用TypeORM操作关系型数据库,首先需要安装相关依赖:

npm install @nestjs/typeorm typeorm mysql2

配置app.module.ts

import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';

@Module({
  imports: [
    TypeOrmModule.forRoot({
      type: 'mysql',
      host: 'localhost',
      port: 3306,
      username: 'root',
      password: 'password',
      database: 'test',
      entities: [__dirname + '/**/*.entity{.ts,.js}'],
      synchronize: true,
    }),
  ],
})
export class AppModule {}

定义实体类user.entity.ts

import { Entity, PrimaryGeneratedColumn, Column } from 'typeorm';

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

  @Column()
  name: string;

  @Column()
  age: number;
}

创建服务user.service.ts

import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { User } from './user.entity';

@Injectable()
export class UserService {
  constructor(
    @InjectRepository(User)
    private usersRepository: Repository<User>,
  ) {}

  findAll(): Promise<User[]> {
    return this.usersRepository.find();
  }

  findOne(id: number): Promise<User> {
    return this.usersRepository.findOneBy({ id });
  }

  async remove(id: number): Promise<void> {
    await this.usersRepository.delete(id);
  }
}

优化方面:

  1. 使用事务处理复杂操作。
  2. 批量插入数据提高效率。
  3. 设置缓存减少数据库查询次数。
  4. 配置数据库连接池以支持高并发。

在NestJS中使用TypeORM操作关系型数据库时,首先要安装必要的依赖:

npm install @nestjs/typeorm typeorm mysql2

接着,在app.module.ts中配置TypeORM模块:

@Module({
  imports: [
    TypeOrmModule.forRoot({
      type: 'mysql',
      host: 'localhost',
      port: 3306,
      username: 'root',
      password: 'password',
      database: 'testdb',
      entities: [__dirname + '/**/*.entity{.ts,.js}'],
      synchronize: true,
    }),
  ],
})
export class AppModule {}

创建实体类如user.entity.ts

import { Entity, PrimaryGeneratedColumn, Column } from 'typeorm';

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

  @Column()
  name: string;

  @Column()
  email: string;
}

然后在服务中注入TypeORM的存储库:

import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { User } from './user.entity';

@Injectable()
export class UserService {
  constructor(
    @InjectRepository(User)
    private usersRepository: Repository<User>,
  ) {}

  async findAll(): Promise<User[]> {
    return this.usersRepository.find();
  }
}

优化方面,可以使用查询构建器或存储库方法来编写复杂的查询,避免全表扫描。例如:

this.usersRepository.createQueryBuilder('user')
  .where('user.age > :age', { age: 18 })
  .getMany();

此外,合理使用索引、分页(takeskip)以及缓存也能显著提升性能。记得在生产环境中关闭synchronize选项并手动管理数据库迁移。

NestJS 中使用 TypeORM 进行数据库操作与优化指南

基本配置

首先安装必要依赖:

npm install @nestjs/typeorm typeorm mysql2  # 或其他数据库驱动

然后在 AppModule 中配置:

import { TypeOrmModule } from '@nestjs/typeorm';

@Module({
  imports: [
    TypeOrmModule.forRoot({
      type: 'mysql',
      host: 'localhost',
      port: 3306,
      username: 'root',
      password: 'password',
      database: 'test',
      entities: [__dirname + '/**/*.entity{.ts,.js}'],
      synchronize: true, // 开发环境使用,生产环境应关闭
    }),
  ],
})
export class AppModule {}

实体定义

import { Entity, PrimaryGeneratedColumn, Column } from 'typeorm';

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

  @Column()
  name: string;

  @Column()
  email: string;
}

基本操作

在服务中使用 Repository:

import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { User } from './user.entity';

@Injectable()
export class UsersService {
  constructor(
    @InjectRepository(User)
    private usersRepository: Repository<User>,
  ) {}

  findAll(): Promise<User[]> {
    return this.usersRepository.find();
  }

  findOne(id: number): Promise<User> {
    return this.usersRepository.findOne(id);
  }

  async create(user: User): Promise<User> {
    return this.usersRepository.save(user);
  }
}

优化技巧

  1. 关系处理
// 一对多关系
@Entity()
export class User {
  @OneToMany(() => Photo, photo => photo.user)
  photos: Photo[];
}

@Entity()
export class Photo {
  @ManyToOne(() => User, user => user.photos)
  user: User;
}
  1. 查询优化
// 使用 relations 进行关联查询
this.usersRepository.find({ relations: ['photos'] });

// 使用 query builder 进行复杂查询
this.usersRepository.createQueryBuilder('user')
  .leftJoinAndSelect('user.photos', 'photo')
  .where('user.name = :name', { name: 'John' })
  .getMany();
  1. 索引优化
@Column()
@Index()
email: string;

// 复合索引
@Index(['firstName', 'lastName'])
  1. 事务处理
async transfer(fromId: number, toId: number, amount: number) {
  await this.connection.transaction(async manager => {
    await manager.decrement(User, { id: fromId }, 'balance', amount);
    await manager.increment(User, { id: toId }, 'balance', amount);
  });
}
  1. 连接池配置
TypeOrmModule.forRoot({
  // ...其他配置
  extra: {
    connectionLimit: 10, // 连接池大小
  }
})

在生产环境中,建议关闭 synchronize 并使用 migrations 管理数据库结构变更。

回到顶部