了解ERD图,如何设计数据库表结构;
一、基础知识
-
表头-字段
-
列
-
主键
唯一标识; 一般是 ID, 也可以是两列,ID & UserName 成为联合主键;
外键:关联两个表
-
关系型,表与表的关系
一对一、一对多、多对多
关系型
MySQL、Oracle、SQL Server、Access、SQLite、postgreSQL
ERD设计:Navicat,dbdesigner,QuickDBD
非关系型
MongoDB、Redis、Hbase、Memcache
二、nestjs中如何配置
1. 依赖安装
在 nest 中使用官方推荐的 ORM 工具 TypeORM,首先下载相关依赖
npm install --save @nestjs/typeorm typeorm mysql2
2. 配置
app.module.ts
import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import { DatabaseModule } from './shared/database/database.module';
import config from '~/config';
import { AppController } from './app.controller';
import { AppService } from './app.service';
@Module({
imports: [
ConfigModule.forRoot({
// 全局配置
isGlobal: true,
// 展开环境变量,将环境变量转换为对象;eg: DB_HOST=localhost -> { DB_HOST: 'localhost' }
expandVariables: true,
// 环境变量文件
envFilePath: ['.env.local', `.env.${process.env.NODE_ENV}`, '.env'],
// 加载配置
load: [...Object.values(config)],
}),
DatabaseModule,
],
// 。。。
})
export class AppModule {}
database.module.ts
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { ConfigService } from '@nestjs/config';
import { dbRegToken, IDatabaseConfig } from '~/config/database.config';
// import { DataSourceOptions } from 'typeorm';
@Module({
imports: [
TypeOrmModule.forRootAsync({
inject: [ConfigService],
useFactory: (configService: ConfigService) => {
const dataSourceOptions = configService.get<IDatabaseConfig>(dbRegToken)
return {
...dataSourceOptions
}
},
}),
],
exports: [],
})
export class DatabaseModule {}
config文件夹下文件:
index.ts
import { DatabaseConfig } from './database.config'
export default {
database: DatabaseConfig,
}
database.config.ts
import { ConfigType, registerAs } from '@nestjs/config'
import { DataSourceOptions } from 'typeorm'
import dotenv from 'dotenv'
dotenv.config({ path: `.env.${process.env.NODE_ENV}` })
/**
* @description 数据源配置
*/
const dataSourceOptions: DataSourceOptions = {
type: 'mysql',
host: process.env.DB_HOST,
port: parseInt(process.env.DB_PORT),
username: process.env.DB_USERNAME,
password: process.env.DB_PASSWORD,
database: process.env.DB_NAME,
}
export const dbRegToken = 'database'
/**
* @nestjs/config 里的这两个是做“类型安全配置”的核心工具:
registerAs:给一组配置命名并注册
你用它把配置包装成一个命名空间,例如 registerAs('database', () => ({ ... }))
这样配置键就变成 database.xxx,方便模块化管理
常用于 src/config/*.config.ts 这种文件里
ConfigType:从 registerAs 的配置工厂中推导 TS 类型
它是一个泛型工具类型:ConfigType<typeof databaseConfig>
可以拿到 databaseConfig 返回对象的精确类型,避免手写接口
常配合 @Inject(databaseConfig.KEY) 注入时使用,让 config.host、config.port 都有类型提示和检查
*/
export const DatabaseConfig = registerAs(
dbRegToken,
(): DataSourceOptions => dataSourceOptions,
)
export type IDatabaseConfig = ConfigType<typeof DatabaseConfig>
.env.development
# Node 环境:production 里建议开启严格配置
NODE_ENV=development
# MySQL 连接信息
DB_HOST=localhost
DB_PORT=3306
DB_USERNAME=root
DB_PASSWORD=12345678
DB_NAME=test_db
Tsconfig.json
{
"compilerOptions": {
"module": "commonjs",
"target": "ES2021",
// .....
// 如下两项配置需要特别注意,
"allowSyntheticDefaultImports": true,
"esModuleInterop": true,
},
}
这两个配置项是 TypeScript 项目中解决模块互操作性问题的关键,尤其是在混用 ES 模块(ESM)和 CommonJS 模块时。它们通常一起开启,以获得更统一、更顺畅的开发体验。
它们共同解决了“用现代的 import 语法去引入旧的 CommonJS 模块”时可能出现的各种不兼容问题。
三、创建一个表(实体)
通过命令行创建一个 users 模块:
nest g res users
到指定的目录下执行以上命令,会自动生成一个 REST API 风格的代码模版;
执行以上命令会生成上图左下角的目录结构,其中 user.entity.ts 则为实体文件;
用户 实体代码如下 user.entity.ts :
import { Entity, PrimaryGeneratedColumn, Column, CreateDateColumn, UpdateDateColumn } from 'typeorm';
@Entity('users')
export class UserEntity {
@PrimaryGeneratedColumn()
id: number;
@Column()
name: string;
@Column()
password: string;
// nullable 设置为 true,表示该字段可以为空
@Column({ nullable: true })
email: string;
@Column({ nullable: true })
phone: string;
@CreateDateColumn({ name: 'created_at' })
createdAt: Date;
@UpdateDateColumn({ name: 'updated_at' })
updatedAt: Date;
}
@Column({ nullable: true }) 这行需要注意,如果字段在创建时不需要(可选),必须设置 nullable: true,否则会报错,参数没有默认值,类似:
Error creating user entity: QueryFailedError: Field 'email' doesn't have a default value
在 users.module.ts 中引入实体
import { UserEntity } from './entities/user.entity';
@Module({
imports: [TypeOrmModule.forFeature([UserEntity])],
// ...
// 如果想在导入了 TypeOrmModule.forFeature 的模块之外使用仓库,您需要重新导出由它生成的提供者。 您可以通过导出整个模块来实现,像这样:
exports: [TypeOrmModule]
})
以上代码配置完成后,启动服务不报错的话就会看到数据库里面自动新增了一个表名为 users,相关字段信息就是我们实体里面配置的字段;