typeorm构建数据库表教程

569 阅读8分钟

环境安装

首先安装和构建数据库表相关的npm包。

  • typescript 是一个由微软开发的编程语言,它是 JavaScript 的一个超集,添加了静态类型支持。使用 TypeScript 可以在开发过程中提供更强的类型检查,帮助开发者在编码阶段发现潜在的错误。在 Nest.js 项目中,TypeScript 通常用于编写应用程序的代码。
  • typeorm 是一个支持多种数据库的对象关系映射(ORM)库,它允许你使用 TypeScript 或 JavaScript 语言编写数据库相关的代码,而不必直接操作 SQL 语句。typeorm 可以帮助你在数据库表和应用程序的数据模型之间建立映射关系,方便地进行数据库的增删改查操作。
  • class-validator 是一个基于类装饰器和方法装饰器的验证库,它可以用于在 Nest.js 应用中验证输入数据的合法性。通过 class-validator,你可以方便地在 DTO(数据传输对象)或实体类上定义验证规则,确保数据的有效性和安全性。
  • @nestjs/typeorm 是 Nest.js 官方提供的一个 TypeORM 模块,用于集成 TypeORM 到 Nest.js 应用中。它简化了在 Nest.js 中使用 TypeORM 的配置和使用,提供了一些装饰器和依赖注入的功能,使得在 Nest.js 中进行数据库操作更加便捷。
  • mysql2 是一个 MySQL 数据库的 Node.js 驱动程序,它提供了异步、非阻塞的 MySQL 数据库连接和查询功能。在 Node.js 应用中,mysql2 可以用于连接 MySQL 数据库服务器,并执行查询、更新、删除等数据库操作。

这些包通常在 Nest.js 项目中一起使用,用于构建具有数据库支持的 Web 应用程序。typescript 用于编写类型安全的代码,typeorm@nestjs/typeorm 用于数据库操作,class-validator 用于验证用户输入,而 mysql2 则是 MySQL 数据库的 Node.js 驱动程序。

    "typescript": "^5.0.0",
    "typeorm": "^0.3.10",
    "class-validator": "^0.13.2",
    "@nestjs/typeorm": "^9.0.1",
    "mysql2": "^2.3.3"

项目结构

Nest.js 项目通常采用模块化的架构,其中每个功能或业务逻辑单元被组织为一个独立的模块。

创建 modules 文件夹:

在你的 Nest.js 项目根目录下创建一个名为 modules 的文件夹。这个文件夹将用于存放所有的模块。

为每个功能创建一个模块文件夹:

在 modules 文件夹下为每个功能或业务逻辑单元创建一个单独的文件夹。例如,如果你的项目需要一个用户模块,可以创建一个名为 user 的文件夹。

具体的文件夹结构如下图:

创建过程

创建user.entity.ts

使用了 Nest.js 中的装饰器和 TypeORM 中的实体(Entity)装饰器,用于定义一个名为 User 的实体类。在这个类中,使用了装饰器来添加元数据和验证规则。

导入了 class-validator 中的 IsNotEmpty 装饰器,用于定义属性的验证规则。同时,还导入了 TypeORM 中的 Column、Entity 和 PrimaryGeneratedColumn 装饰器,用于定义数据库表的结构和字段。

其中@Entity('user'):是 TypeORM 中的实体装饰器,用于指定实体在数据库中的表名为 'user'。

export class User { ... }:定义了一个名为 User 的类,表示数据库中的用户实体。

在TypeORM中,@Entity 是一个装饰器,用于将一个类标记为一个数据库实体(Entity)。数据库实体通常对应数据库中的一张表,每个实体类的实例代表了表中的一行数据。使用 @Entity 装饰器,你可以告诉TypeORM将这个类映射到数据库中的哪个表。

在给 @Entity 装饰器传递参数时,你可以指定实体在数据库中的表名。@Entity('user') 中的 'user' 参数指定了这个实体在数据库中的表名为 'user'。TypeORM 将会使用这个表名来创建数据库表,并且将 User 类的实例映射到这个表中的数据记录。

如果不指定表名,默认情况下,TypeORM 将使用类名作为数据库表的名称。但是,通过传递参数给 @Entity 装饰器,你可以自定义实体在数据库中的表名,使得类名和表名之间可以有所区别。

@Entity('user')
export class User {

其次定义实体中的属性:

@PrimaryGeneratedColumn('uuid') id: string;:使用 @PrimaryGeneratedColumn 装饰器定义了一个自动生成的主键字段 id,类型为 string,并且使用了 uuid 数据类型。

@Column({ comment: '昵称', default: '' }) @IsNotEmpty() name: string;:使用 @Column 装饰器定义了一个名为 name 的字段,指定了该字段在数据库中的注释为 '昵称',默认值为空字符串 '',并且使用了 @IsNotEmpty() 装饰器,表示该字段不能为空

同样的方式定义了 desc、tel、password 和 account 字段,每个字段都有相应的注释和验证规则。

 @PrimaryGeneratedColumn('uuid')
 id: string;

 @Column({
   comment: '昵称',
   default: '',
 })
 @IsNotEmpty()
 name: string;

 @Column({
   comment: '描述',
   default: '',
 })
 desc: string;

 @Column({
   comment: '手机号',
   nullable: true,
 })
 tel: string;

 @Column({
   comment: '密码',
   nullable: true,
 })
 password: string;

 @Column({
   comment: '账户',
   nullable: true,
 })
 account: string;

总的来说,这段代码定义了一个数据库实体 User,该实体具有 id、name、desc、tel、password 和 account 六个字段。其中 name 字段必须非空。这个实体可以被 TypeORM 映射到数据库中的 user 表。完整代码如下:

import { IsNotEmpty } from 'class-validator';
import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm';

/**
 * 组件
 */
@Entity('user')
  export class User {
    @PrimaryGeneratedColumn('uuid')
    id: string;

    @Column({
      comment: '昵称',
      default: '',
    })
    @IsNotEmpty()
    name: string;

    @Column({
      comment: '描述',
      default: '',
    })
    desc: string;

    @Column({
      comment: '手机号',
      nullable: true,
    })
    tel: string;

    @Column({
      comment: '密码',
      nullable: true,
    })
    password: string;

    @Column({
      comment: '账户',
      nullable: true,
    })
    account: string;
  }

创建src/modules/user/user.module.ts

  • Module 和 ConsoleLogger 是 Nest.js 中的模块和日志记录器。
  • TypeOrmModule 是 Nest.js 中用于集成 TypeORM 到 Nest.js 应用中的模块。
  • User 是一个数据库实体,位于 ./models/user.entity 文件中。
import { Module, ConsoleLogger } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { User } from './models/user.entity';

@Module({
  imports: [TypeOrmModule.forFeature([User])],
  providers: [ConsoleLogger],
  exports: [],
})
export class UserModule {}

@Module 装饰器用于定义 Nest.js 模块。在这里,UserModule 是一个 Nest.js 模块的类。

在Nest.js中,@Module 装饰器用于定义一个模块。模块是Nest.js应用程序的基本组织单元,它用于将相关的组件、控制器、服务等功能单元组织在一起。使用 @Module 装饰器,你可以创建一个模块并且指定模块所包含的组件、控制器、服务等。

在上面提到的代码中,@Module 装饰器被用于定义一个名为 UserModule 的Nest.js模块。@Module 装饰器接受一个配置对象作为参数,该配置对象包含以下属性:

  • imports:一个数组,用于指定模块所依赖的其他模块。在这个例子中,使用 TypeOrmModule.forFeature([User]) 将 TypeOrmModule 导入到模块中,并告诉TypeORM该模块会使用 User 实体。imports 数组通常包含导入的外部模块,用于扩展当前模块的功能。
  • providers:一个数组,用于指定模块中的提供者(服务、工厂等)。在这个例子中,提供了一个 ConsoleLogger 实例作为提供者。提供者是模块中可被依赖注入的对象。
  • exports:一个数组,用于指定该模块向外部暴露的组件、服务等。在这个例子中,exports 数组为空,表示该模块不向外部暴露任何组件或服务。

综上,本小章的代码主要完成了以下几个任务:

  • 导入了 TypeOrmModule,并告知 TypeORM 该模块会使用 User 实体。
  • 注入了一个 ConsoleLogger 实例,以供模块内的其他组件或服务使用。
  • 不导出任何内容,意味着其他模块无法直接引用 UserModule 中的组件或服务。

创建src/app.module.ts

主要导入模块如下:

  • Module:Nest.js 中的模块装饰器,用于定义一个 Nest.js 模块。
  • AppController 和 AppService:这是当前模块使用的控制器和服务,它们被导入并在模块中使用。
  • TypeOrmModule:用于集成 TypeORM 到 Nest.js 应用中的模块。
  • UserModule:另一个 Nest.js 模块,它被导入并在当前模块中使用。

@Module 装饰器用于定义 Nest.js 模块。在这个例子中,AppModule 是一个 Nest.js 模块的类。

imports 数组中导入了 TypeOrmModuleUserModule

TypeOrmModule.forRoot() 方法用于配置数据库连接。

TypeOrmModule.forRoot() 方法接受一个配置对象作为参数,该配置对象包含了连接数据库所需的各种信息:

  • type: 指定数据库的类型,例如 'mysql'、'postgres'、'sqlite' 等。
  • host: 数据库服务器的主机地址。
  • port: 数据库服务器的端口号。
  • username: 连接数据库的用户名。
  • password: 连接数据库的密码。
  • database: 要连接的数据库名称。
  • entities: 指定实体类,即 TypeORM 映射到数据库表的实体。在上述例子中,User 是一个实体类。
  • synchronize: 设置为 true 时,每次应用启动时都会根据实体类自动创建数据库表。在开发环境中,可以使用这个选项方便地创建数据库表。在生产环境中,通常设置为 false,避免应用程序自动修改数据库结构。
  • logging: 是否启用数据库日志记录,用于记录数据库操作的日志。在开发环境中,可以设置为 true,以便调试和查看数据库操作的日志。在生产环境中,通常设置为 false,以提高性能。

UserModule 是应用程序的另一个模块,被导入到当前模块中。

controllers 数组中指定了该模块中使用的控制器,这里是 AppController。

providers 数组中指定了该模块中使用的服务,这里是 AppService。

import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { TypeOrmModule } from '@nestjs/typeorm';
import { UserModule } from './modules/user/user.module';

@Module({
  imports: [
    TypeOrmModule.forRoot({
      type: 'mysql',
      host: 'X.X.X.X',
      port: 3306,
      username: 'root',
      password: '123456',
      database: 'healthflex',
      entities: [`${__dirname}/../modules/**/*.entity{.ts,.js}`],
      logging: true,
      synchronize: true,
      autoLoadEntities: true,
    }),
    UserModule,
  ],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

随后执行nest项目,可以看出成功创建数据库表user。

pnpm run start