【NestJs】数据库重构

news2024/11/19 13:40:56

上一篇文章详细了介绍nestjs 配置数据库,有不懂的小伙伴可以先查看上一篇文章【NestJs】使用连接mysql企业级开发规范在继续往下。
今天这一篇文章主要是针对配置数据库的重构,使用代码规范,方便后期维护。
当应用变得复杂 我们需要借用TypeORM CLI 非常方便的调整。

注意:
TypeORM 读取到extensions 结尾的文件
在这里插入图片描述
但是在根目录的文件 不能进行动态的修改,这样的话变量一旦很多的,修改极其麻烦。
在这里插入图片描述
当然 我们选择 ormconfig.ts ,不过因为我们环境不止一个。需要多多个环境校验。

使用 CLI

此 CLI 工具使用 javascript 编写,并在 node 上运行。如果你的实体文件是 TypeScript 编写,则需要在使用 CLI 之前将它们转换为 javascript。如果只使用 javascript,则可以跳过此部分。

全局安装 ts-node:

你可以在项目中设置 ts-node 以简化操作,如下所示:

npm install ts-node --save-dev

在 package.json 中的 scripts 下添加 typeorm 命令

"script" {
    ...
    "typeorm": "typeorm-ts-node-commonjs"
}

注意:
typeorm 该版本使用的是 “typeorm”: “0.3.7” 要是版本不一致 需要查看官方文档最新使用方法。

根目录创建文件ormconfig.ts,我们需要把app.module.ts配置的数据库迁移:

import { User } from './src/user/user.entity';
import { Profile } from './src/user/profile.entity';
import { Logs } from './src/logs/logs.entity';
import { Roles } from './src/roles/roles.entity';
import { TypeOrmModuleOptions } from '@nestjs/typeorm';

export default {
  type: 'mysql',
  host: 'localhost',
  port: 3306,
  username: 'root',
  password: '123456',
  database: 'testdb',
  entities: [User, Profile, Logs, Roles],
  // 同步本地的schema与数据库 -> 初始化的时候去使用
  synchronize: true,
  // logging: process.env.NODE_ENV === 'development',
  logging: false,
} as TypeOrmModuleOptions;

app.module.ts

import { Global, Logger, Module } from '@nestjs/common';
import { UserModule } from './user/user.module';
import { ConfigModule } from '@nestjs/config';
import * as dotenv from 'dotenv';
import * as Joi from 'joi';
import { TypeOrmModule } from '@nestjs/typeorm';

import { LogsModule } from './logs/logs.module';
import { RolesModule } from './roles/roles.module';
import ormconfig from '../ormconfig';

const envFilePath = `.env.${process.env.NODE_ENV || `development`}`;

@Global()
@Module({
  imports: [
    ConfigModule.forRoot({
      isGlobal: true,
      envFilePath,
      load: [() => dotenv.config({ path: '.env' })],
      validationSchema: Joi.object({
        NODE_ENV: Joi.string()
          .valid('development', 'production')
          .default('development'),
        DB_PORT: Joi.number().default(3306),
        DB_HOST: Joi.string().ip(),
        DB_TYPE: Joi.string().valid('mysql', 'postgres'),
        DB_DATABASE: Joi.string().required(),
        DB_USERNAME: Joi.string().required(),
        DB_PASSWORD: Joi.string().required(),
        DB_SYNC: Joi.boolean().default(false),
      }),
    }),
    TypeOrmModule.forRoot(ormconfig),
    UserModule,
    LogsModule,
    RolesModule,
  ],
  controllers: [],
  providers: [Logger],
  exports: [Logger],
})
export class AppModule {}

在这里插入图片描述
到这里 说明连接成功了。

初始化一个新的TypeORM项目

它使用 TypeORM 创建基本项目所需的所有文件:

  • .gitignore
  • package.json
  • README.md
  • tsconfig.json
  • ormconfig.json
  • src/entity/User.ts
  • src/index.ts
    然后你可以运行npm install来安装所有依赖项。 一旦安装了所有依赖项,你需要修改ormconfig.json并插入您自己的数据库设置。 之后,可以通过运行npm start来运行您的应用程序。

要指定使用的特定数据库,可以使用–database:

npx typeorm init --database mysql2

生成文件data-source.ts 文件结构和ormconfig 类似,

import 'reflect-metadata';
import { DataSource } from 'typeorm';
import { User } from './entity/User';

export const AppDataSource = new DataSource({
  synchronize: true,
  logging: false,
  entities: [User],
  migrations: [],
  subscribers: [],
});

也会生成一个entity文件夹,暂时不用 我们可以先删掉,根据文档我们需要使用new DataSource 接下来需要修改 ormconnfig.ts 文件

import { User } from './src/user/user.entity';
import { Profile } from './src/user/profile.entity';
import { Logs } from './src/logs/logs.entity';
import { Roles } from './src/roles/roles.entity';
import { TypeOrmModuleOptions } from '@nestjs/typeorm';
import { DataSource, DataSourceOptions } from 'typeorm';

export const connectionParams = {
  type: 'mysql',
  host: 'localhost',
  port: 3306,
  username: 'root',
  password: '123456',
  database: 'testdb',
  entities: [User, Profile, Logs, Roles],
  // 同步本地的schema与数据库 -> 初始化的时候去使用
  synchronize: true,
  // logging: process.env.NODE_ENV === 'development',
  logging: false,
} as TypeOrmModuleOptions;

export default new DataSource({
  ...connectionParams,
  migrations: ['src/migrations/**'],
} as DataSourceOptions);

测试:
修改index.ts

import AppDataSource from '../ormconfig';
import { User } from './user/user.entity';

AppDataSource.initialize()
  .then(async () => {
    const res = await AppDataSource.manager.find(User);
    console.log(res);
  })
  .catch((error) => console.log(error));

npx ts-node src/index.ts

结果:
在这里插入图片描述
到此 我们已经完成了一半。

我们需要使用ormconfig 对接不同的环境?
通过环境变量读取不用的.env文件, 通过dotENV来解析不同的配置:

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

import { DataSource, DataSourceOptions } from 'typeorm';
import * as fs from 'fs';
import * as dotenv from 'dotenv';
import { ConfigEnum } from './src/enum/config.enum';

// 通过环境变量读取不同的.env文件
function getEnv(env: string): Record<string, unknown> {
  if (fs.existsSync(env)) {
    return dotenv.parse(fs.readFileSync(env));
  }
  return {};
}

// 通过dotENV来解析不同的配置
function buildConnectionOptions() {
  const defaultConfig = getEnv('.env');
  const envConfig = getEnv(`.env.${process.env.NODE_ENV || 'development'}`);
  // configService
  const config = { ...defaultConfig, ...envConfig };

  // 过多的实体 我们就不需要一个一个的导入加载
  const entitiesDir =
    process.env.NODE_ENV === 'test'
      ? [__dirname + '/**/*.entity.ts']
      : [__dirname + '/**/*.entity{.js,.ts}'];

  return {
    type: config[ConfigEnum.DB_TYPE],
    host: config[ConfigEnum.DB_HOST],
    port: config[ConfigEnum.DB_PORT],
    username: config[ConfigEnum.DB_USERNAME],
    password: config[ConfigEnum.DB_PASSWORD],
    database: config[ConfigEnum.DB_DATABASE],
    entities: entitiesDir,
    // 同步本地的schema与数据库 -> 初始化的时候去使用
    synchronize: true,
    // logging: process.env.NODE_ENV === 'development',
    logging: false,
  } as TypeOrmModuleOptions;
}

export const connectionParams = buildConnectionOptions();

export default new DataSource({
  ...connectionParams,
  migrations: ['src/migrations/**'],
  subscribers: [],
} as DataSourceOptions);

app.module.ts Joi 的配置需要修改一下:

import { Global, Logger, Module } from '@nestjs/common';
import { UserModule } from './user/user.module';
import { ConfigModule } from '@nestjs/config';
import * as dotenv from 'dotenv';
import * as Joi from 'joi';
import { TypeOrmModule } from '@nestjs/typeorm';

import { LogsModule } from './logs/logs.module';
import { RolesModule } from './roles/roles.module';

import { connectionParams } from '../ormconfig';

const envFilePath = `.env.${process.env.NODE_ENV || `development`}`;

@Global()
@Module({
  imports: [
    ConfigModule.forRoot({
      isGlobal: true,
      envFilePath,
      load: [() => dotenv.config({ path: '.env' })],
      validationSchema: Joi.object({
        NODE_ENV: Joi.string()
          .valid('development', 'production')
          .default('development'),
        DB_PORT: Joi.number().default(3306),
        // 生产环境和部署环境可能 HOST 一个是ip 一个是网址一样
        DB_HOST: Joi.alternatives().try(
          Joi.string().ip(),
          Joi.string().domain(),
        ),
        DB_TYPE: Joi.string().valid('mysql', 'postgres'),
        DB_DATABASE: Joi.string().required(),
        DB_USERNAME: Joi.string().required(),
        DB_PASSWORD: Joi.string().required(),
        DB_SYNC: Joi.boolean().default(false),
        LOG_ON: Joi.boolean(),
        LOG_LEVEL: Joi.string(),
      }),
    }),
    TypeOrmModule.forRoot(connectionParams),
    UserModule,
    LogsModule,
    RolesModule,
  ],
  controllers: [],
  providers: [Logger],
  exports: [Logger],
})
export class AppModule {}

最后就是package.json 中 按照官方文档修改的配置:

"scripts": {
      "prebuild": "rimraf dist",
      "build": "cross-env NODE_ENV=production nest build",
      "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
      "start": "ts-node src/index.ts",
      "start:dev": "cross-env NODE_ENV=development nest start --watch",
      "start:debug": "cross-env NODE_ENV=development nest start --debug --watch",
      "start:prod": "cross-env NODE_ENV=production node dist/src/main",
      "lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
      "test": "jest",
      "test:watch": "jest --watch",
      "test:cov": "jest --coverage",
      "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
      "test:e2e": "jest --config ./test/jest-e2e.json",
      "typeorm": "typeorm-ts-node-commonjs -d ormconfig.ts",
      "migration:generate": "f() { npm run typeorm migration:generate -p \"./src/migrations/$@\"; }; f",
      "migration:create": "typeorm-ts-node-commonjs migration:create",
      "migration:run": "npm run typeorm migration:run",
      "migration:revert": "npm run typeorm migration:revert",
      "schema:drop": "npm run typeorm schema:drop"
   },

运行代码即可。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/451199.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

webstorm常用快捷键

webstorm作为前端代码JavaScript开发的利器&#xff0c;真的特别好用&#xff0c;我就总结一下我工作中经常用到的快捷键&#xff0c;有些快捷键是我自定义配置的&#xff0c;是以mac电脑来总结这篇文章的&#xff0c;请知晓&#xff1a; 自定义配置快捷键&#xff1a; 常用快…

SpringCloud源码探析(五)-网关Gateway的使用

1.概述 在微服务架构中&#xff0c;网关提供了统一的对外访问入口&#xff08;自身跨一个或多个服务&#xff09;&#xff0c;它保证了内部服务对外暴露的合理性与安全性、降低了服务之间访问的复杂性&#xff0c;是微服务架构中至关重要的一部分。在SpringCloud中网关主要包含…

让观众近距离感受如然之光 lipro智能家居成上海车展亮点之一

近段时间&#xff0c;上海国际车展如火如荼地举行&#xff0c;吸引了众多汽车厂商及相关企业参展。在本次展会上&#xff0c;星纪魅族集团也携手亿咖通科技&#xff0c;以联合参展的形式登陆「上海国际车展」 6.1号馆&#xff0c;共同展示智能汽车解决方案及产品创新。此外&…

第十四届蓝桥杯研究生组2023年省赛题解--全部采用Java语言实现

引言 今天现在这里 挖个坑&#xff0c;太忙了&#xff0c;这个专题不一样有时间补完&#xff0c;但我会尽力而为的。记录一下今天的日子&#xff1a;2023/04/21 看看这个坑要什么时候自己才能补完。 题目pdf下载&#xff1a;第十四届蓝桥杯研究生组pdf下载 在此特别感谢博主…

flac转换成mp3,4种方法教会你

怎么把flac转换成mp3&#xff1f;由于互联网技术的不断提升&#xff0c;我们每天接触到的各种音频格式变得越来越多样化。然而&#xff0c;有些特殊格式的音频会在处理时带来一定困难&#xff0c;因为它们的兼容性较差&#xff0c;不能在常用播放器上正常播放&#xff0c;这就给…

React面试题

React 如何创建一个react的项目&#xff08;使用脚手架&#xff09; 安装cr脚手架&#xff1a;npm install -g create-react-app进入文件夹&#xff1a;create-react-app 项目名称进入项目&#xff1a;cd 项目名称运行项目&#xff1a;npm start 如何不使用脚手架创建一个项…

maven打包学习

这篇文章不错&#xff1a; 思考&#xff1a;打包的时候是按照当前项目为标准打包的&#xff0c;那么所有的冲突都会以当前pom为根pom打包。那么&#xff0c;如果jar冲突&#xff0c;会用当前pom的依赖jar。 根据这个文章做了个有趣的实验&#xff1a; object3 //install 2个…

深度强化学习——第一次知识小结(3.5)

一、策略网络的小结&#xff1a; 重要概念回顾&#xff1a; 1、动作价值函数QΠ(st,at) 动作价值函数是未来奖励总和Ut的条件期望&#xff0c;如果已知了策略函数Π与当前的状态st&#xff0c;QΠ就可以对所有的动作a打分&#xff0c;以此来决定选择哪个a 其实顾名思义就是…

2023第14届蓝桥杯C/C++A组省赛题解

省一了&#xff0c;占个坑&#xff0c;今天晚上来补蓝桥的题 试题 A: 幸运数 本题总分&#xff1a;5 分 【问题描述】 小蓝认为如果一个数含有偶数个数位&#xff0c;并且前面一半的数位之和等于后面 一半的数位之和&#xff0c;则这个数是他的幸运数字。例如 2314 是…

ROC的理解

ROC 的由来 ROC 曲线是由混淆矩阵衍生来的指标。 混淆矩阵如图所示&#xff0c; 二ROC曲线的横坐标为 FPR&#xff0c;纵坐标为 TPR&#xff0c;计算公式分别是 F P R F P F P T N , 也就是 F P R F P F A L S E FPR \frac{FP}{FPTN}, 也就是 FPR \frac{FP}{FALSE} FP…

5天学会Linux C高级

day1 用C语言的理论知识点去推断结果 需求&#xff1a;让面试官知道你懂这个内容 一、C语言补充内容 【1】结构体补充内容&#xff1a; 1&#xff09;结构体.等法 结构体.等法代码 #include <stdio.h> struct student { int num; float score; char name[32…

docker镜像创建|实战案例(ssh|systemd|nginx|apache)

docker镜像创建|实战案例&#xff08;ssh|systemd|nginx|apache&#xff09; 一 Docker 镜像的创建1.基于现有镜像创建2基于本地模板创建3 基于Dockerfile 创建为什么Docker里的centos的大小才200M&#xff1f;DockerfileDocker 镜像结构的分层 4 Dockerfile 案例&#xff08;h…

Java IO数据流

Java IO数据流介绍 在程序开发中&#xff0c;将不同输入/输出设备&#xff08;例如文件、网络、压缩包等&#xff09;之间的数据传输抽象为流。可以将流分为字节流&#xff08;以Stream结尾的流&#xff09;和字符流&#xff08;以Reader和Writer结尾的流&#xff09;两种 try…

水羊转债,超达转债,晓鸣转债上市价格预测

水羊转债 基本信息 转债名称&#xff1a;水羊转债&#xff0c;评级&#xff1a;A&#xff0c;发行规模&#xff1a;6.94987亿元。 正股名称&#xff1a;水羊股份&#xff0c;今日收盘价&#xff1a;13.94元&#xff0c;转股价格&#xff1a;13.71元。 当前转股价值 转债面值 /…

5.3 Mybatis映射文件 - 零基础入门,轻松学会查询的select标签和resultMap标签

本文目录 前言一、创建XML映射文件二、MybatisX插件安装三、mapper标签四、select标签UserMapper接口方法UserMapper.xml 五、resultMap标签定义resultMap标签修改select标签 总结 前言 MyBatis的强大在于它的语句映射&#xff0c;它提供了注解和XML映射文件两种开发方式&…

jenkins——邮件告警

文章目录 一、下载 Email Extension 插件二、修改系统配置项目1、Jenkins Location配置2、邮件通知配置&#xff08;用于测试连通性&#xff09;3、Extended E-mail Notification配置4、Jenkins Location 配置5、在 job 中配置邮件发送6、高级设置7、配置发送 trigger8、构建验…

arduino学习笔记3

一.RGB三色小灯实验 1.源代码 int rgb_R11;//接到板子上面的PWM口11 R int rgb_G9;//接到板子上面的PWM口9 G int rgb_B10;//接到板子上面的PWM口10 B void setup() {pinMode(rgb_R,OUTPUT);//设置rgb_R的控制口为输出模式pinMode(rgb_G,OUTPUT);//设置rgb_G的控制口为输出模…

多线程【进阶版】

目录 一. 常见的锁策略 1.1 乐观锁和悲观锁 1.2 轻量级锁和重量级锁 1.3 自旋锁和挂起等待锁 1.4 互斥锁和读写锁 1.5 可重入锁和不可重入锁 1.6 公平锁和非公平锁 1.7 关于锁策略的相关面试题 二. CAS 三. Synchronized 原理 3.1 基本特点 3.2 加锁步骤 3.3 锁消除…

利用宏简化Q_PROPERTY动态属性的定义

目录 写在前面实现历程传统定义方式预想的方式(事实上有一点点区别) 例程mainwindow.hmainwindow.cppmain.cpp 执行结果如上事实的使用方法 写在前面 上一篇写了pyqt如何更加便利地定义动态属性&#xff0c;关于C版的其实在我刚接触Qt不久就想过并做了一些尝试&#xff0c;但死…

C. Vus the Cossack and Strings(异或判断二进制位匹配数奇偶)

Problem - C - Codeforces 题目描述 Vus the Cossack has two binary strings, that is, strings that consist only of "0" and "1". We call these strings aa and bb . It is known that |b| \leq |a|∣b∣≤∣a∣ , that is, the length of bb is at m…