Nestjs项目实战 集成TypeORM实现数据库操作

在NestJS项目中集成TypeORM时遇到几个问题想请教:

  1. 如何正确配置TypeORM模块连接数据库?我的ormconfig.json总是报错,有没有推荐的最佳实践?

  2. 实体类(Entity)与数据库表字段的映射关系该如何定义?比如主键、外键、枚举类型的处理。

  3. 在Service中调用TypeORM的Repository时,是直接注入Repository好,还是通过自定义Provider封装更好?

  4. 遇到复杂查询(如联表、分页)时,用QueryBuilder和原生SQL哪种方式更合适?

  5. 有没有优雅处理事务的方法?目前用EntityManager感觉代码比较冗余。

项目用的是MySQL,NestJS版本是v9。


3 回复

在NestJS项目中集成TypeORM实现数据库操作的步骤如下:

  1. 安装依赖:使用npm或yarn安装必要的包:

    npm install [@nestjs](/user/nestjs)/typeorm typeorm mysql2
    

    这里以MySQL为例,如果用其他数据库,需安装对应的驱动。

  2. 配置TypeORM模块:在app.module.ts中引入并配置TypeORM:

    import { Module } from '[@nestjs](/user/nestjs)/common';
    import { TypeOrmModule } from '[@nestjs](/user/nestjs)/typeorm';
    
    [@Module](/user/Module)({
      imports: [
        TypeOrmModule.forRoot({
          type: 'mysql',
          host: 'localhost',
          port: 3306,
          username: 'root',
          password: '',
          database: 'test_db',
          entities: [__dirname + '/**/*.entity{.ts,.js}'],
          synchronize: true, // 开发环境建议开启
        }),
      ],
    })
    export class AppModule {}
    
  3. 创建实体类:通过TypeORM定义数据表结构,例如user.entity.ts

    import { Entity, PrimaryGeneratedColumn, Column } from 'typeorm';
    
    [@Entity](/user/Entity)()
    export class User {
      @PrimaryGeneratedColumn()
      id: number;
    
      @Column()
      name: string;
    
      @Column()
      email: string;
    }
    
  4. 编写服务层:利用注入的EntityManager进行增删改查操作。例如:

    import { Injectable } from '[@nestjs](/user/nestjs)/common';
    import { InjectRepository } from '[@nestjs](/user/nestjs)/typeorm';
    import { Repository } from 'typeorm';
    import { User } from './user.entity';
    
    [@Injectable](/user/Injectable)()
    export class UserService {
      constructor(
        @InjectRepository(User)
        private usersRepository: Repository<User>,
      ) {}
    
      async createUser(name: string, email: string): Promise<User> {
        const user = new User();
        user.name = name;
        user.email = email;
        return await this.usersRepository.save(user);
      }
    }
    
  5. 路由与控制器绑定:在Controller中调用Service完成CRUD逻辑。

遵循以上步骤即可完成基本的数据库操作集成。


在NestJS项目中集成TypeORM进行数据库操作非常简单。首先,在package.json中安装必要的依赖:

npm install @nestjs/typeorm typeorm mysql2 --save

然后,在app.module.ts中配置TypeORM模块:

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_db',
      entities: [__dirname + '/**/*.entity{.ts,.js}'],
      synchronize: true, // 生产环境建议关闭
    }),
  ],
})
export class AppModule {}

接着定义实体类,比如创建一个User实体:

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

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

  @Column()
  name: string;

  @Column()
  age: number;
}

最后,在服务中注入Repository来操作数据库:

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 create(user: Partial<User>): Promise<User> {
    const newUser = this.usersRepository.create(user);
    return this.usersRepository.save(newUser);
  }

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

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

这样就完成了基本的数据库操作功能。

NestJS 集成 TypeORM 实现数据库操作

TypeORM 是 Node.js 中最流行的 ORM 之一,与 NestJS 集成良好。下面是实战步骤:

1. 安装必要依赖

npm install @nestjs/typeorm typeorm mysql2  # 根据数据库选择相应驱动

2. 配置数据库连接

app.module.ts 中配置:

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 {}

3. 创建实体(Entity)

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

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

  @Column()
  name: string;

  @Column()
  email: string;
}

4. 创建服务层

// users.service.ts
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({ where: { id } });
  }

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

  async update(id: number, user: Partial<User>): Promise<User> {
    await this.usersRepository.update(id, user);
    return this.usersRepository.findOne({ where: { id } });
  }

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

5. 创建控制器

// users.controller.ts
import { Controller, Get, Post, Body, Param, Put, Delete } from '@nestjs/common';
import { UsersService } from './users.service';
import { User } from './user.entity';

@Controller('users')
export class UsersController {
  constructor(private readonly usersService: UsersService) {}

  @Get()
  findAll() {
    return this.usersService.findAll();
  }

  @Get(':id')
  findOne(@Param('id') id: string) {
    return this.usersService.findOne(+id);
  }

  @Post()
  create(@Body() user: User) {
    return this.usersService.create(user);
  }

  @Put(':id')
  update(@Param('id') id: string, @Body() user: Partial<User>) {
    return this.usersService.update(+id, user);
  }

  @Delete(':id')
  remove(@Param('id') id: string) {
    return this.usersService.remove(+id);
  }
}

6. 注册模块

// users.module.ts
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { UsersService } from './users.service';
import { UsersController } from './users.controller';
import { User } from './user.entity';

@Module({
  imports: [TypeOrmModule.forFeature([User])],
  providers: [UsersService],
  controllers: [UsersController],
})
export class UsersModule {}

高级特性

  1. 关系:可以使用 @OneToMany@ManyToOne 等装饰器定义关系
  2. 事务:使用 @Transaction@TransactionManager 装饰器
  3. 查询构建器:通过 repository.createQueryBuilder() 构建复杂查询
  4. 分页:使用 skiptake 参数

生产环境中,建议关闭 synchronize 选项,使用迁移来管理数据库结构变更。

回到顶部