nestjs+typeorm动态建表及查询

之前因工作需要在 midwayjs 项目中需要使用动态建表及查询功能,所以写过一篇midway+typeorm 动态建表及查询 然后收到一条评论,问能不能发个 nestjs 项目中动态建表和查询的。这都过了三个星期了,一来是工作略忙,二来是要陪娃,所以一直也没有回复。也许留言的同学已经自己实现了相关功能了。但想着还是回复一下,所以又写了这篇文章。

直接上代码说功能

midwayjs 和 nestjs 要连接数据库可以通过很多不同的 orm 库来实现,而不同的 orm 库实现动态建表肯定是不一样的,这里还是拿 typeorm 来说吧,其实和 midway 中一样,主要就是拿到 dataSource , 剩下的都是 typeorm 的事了,不管在哪个框架下,只要使用的是 typeorm,那动态建表及查询的方式都可以直接搬来用

ts 复制代码
// 这是单独的工具类文件
import { DataSource, Entity, Table } from 'typeorm';
import { ConnectionMetadataBuilder } from 'typeorm/connection/ConnectionMetadataBuilder';
import BaseEntity from './entities/base.entity';

let dataSource: DataSource;

// 设置 dataSource
export function setDataSource(d: DataSource) {
  dataSource = d;
}

async function buildMetadata(entity: typeof BaseEntity) {
  const [entityMetadata] = await new ConnectionMetadataBuilder(
    dataSource,
  ).buildEntityMetadatas([entity]);
  dataSource.entityMetadatas.push(entityMetadata);
  dataSource.entityMetadatasMap.set(entityMetadata.target, entityMetadata);
}

const entityMap = new Map<string, typeof BaseEntity>();
// 根据 name 获取/新建一个 Entity
export async function getEntity(name: string) {
  if (entityMap.has(name)) {
    return entityMap.get(name);
  }

  const tableName = `dynamic_${name}`;

  @Entity(tableName)
  class DynamicEntity extends BaseEntity {}

  await buildMetadata(DynamicEntity);

  entityMap.set(name, DynamicEntity);
  return DynamicEntity;
}

async function getMetadata(name: string) {
  const entity = await getEntity(name);
  return dataSource.getMetadata(entity);
}

// 动态建表
export async function dynamicCreateTable(name: string) {
  const metadata = await getMetadata(name);
  const runner = dataSource.createQueryRunner();
  await runner.createTable(Table.create(metadata, dataSource.driver));
  await runner.release();
}

// 获取 repositry 以便后续的查询等操作
export async function getRepositry(name: string) {
  const entity = await getEntity(name);
  return dataSource.getRepository<typeof BaseEntity>(entity);
}

在业务代码中调用 dynamicCreateTable 来创建新表

ts 复制代码
async createTable(name: string) {
  // 调用导入的方法
  await dynamicCreateTable(name);
  return name;
}

或者查询业务

ts 复制代码
async queryTable(name: string) {
  const repositry = await getRepositry(name);
  // 获取到 repositry 之后的用法和注入获取的使用方式是一样的
  return repositry.find();
}

在 midwayjs 的项目中,在工具类文件中获取 dataSource是通过下面这个方法获取的

ts 复制代码
import { getCurrentApplicationContext } from '@midwayjs/core';
import { TypeORMDataSourceManager } from '@midwayjs/typeorm';

export async function getDataSource() {
  const sourceManager = await getCurrentApplicationContext().getAsync(TypeORMDataSourceManager);
  return sourceManager.getDataSource('default');
}

但是在 nestjs 中并未发现类似的方法,基本都是通过注入的方法获取的。但是在这个工具类文件中就是一堆函数的集合,不好使用注入。所以在 nestjs 项目中我选择了增加一个 dataSource 变量并增加了 setDataSource 方法。并在项目启动后手动调用此方法设置 dataSource

ts 复制代码
// main.ts文件
// 一堆 import 没写
async function bootstrap() {
  const app = await NestFactory.create(AppModule);

  const dataSource = app.get(DataSource);
  // 调用从工具文件导入的设置方法
  setDataSource(dataSource);

  await app.listen(3000);
}
bootstrap();

这种方式怎么看都不是最优的方式,不知道在 nestjs 框架中有没有其他更好的方式,有知道的大佬可以留言告知一下,非常感谢🤝


其实我也没用过 nestjs 这个框架。平时工作主要还是前端网页那些东西,这些后端服务/数据库部分日常工作都不怎么涉及。但是如果只是动态建表及查询功能,所以和 midway 项目中实现还是基本一样的,唯一的差别就是上面说如何获取 dataSource 对象。希望这篇文章能有点用的吧,迟到的答复。

相关推荐
李游Leo8 小时前
Node.js 多版本管理与 nvm/nvs 使用全流程(含国内镜像加速与常见坑)
node.js
Q_Q19632884759 小时前
python+springboot+uniapp微信小程序题库系统 在线答题 题目分类 错题本管理 学习记录查询系统
spring boot·python·django·uni-app·node.js·php
陈随易14 小时前
适合中国宝宝的AI编程神器,文心快码
前端·后端·node.js
Q_Q196328847516 小时前
python+springboot大学生心理测评与分析系统 心理问卷测试 自动评分分析 可视化反馈系统
开发语言·spring boot·python·django·flask·node.js·php
EndingCoder18 小时前
Electron 新特性:2025 版本更新解读
前端·javascript·缓存·electron·前端框架·node.js·桌面端
machinecat19 小时前
node,小程序合成音频的方式
前端·node.js
草木红1 天前
express 框架基础和 EJS 模板
arcgis·node.js·express
亮子AI2 天前
【npm】npm 包更新工具 npm-check-updates (ncu)
前端·npm·node.js
Yvonne爱编码2 天前
构建高效协作的桥梁:前后端衔接实践与接口文档规范详解
前端·git·ajax·webpack·node.js
Juchecar2 天前
AI教你常识之 ESM + Express + Vue3 + CSV文件 + Pinia + CRUD
node.js