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 对象。希望这篇文章能有点用的吧,迟到的答复。

相关推荐
理想不理想v7 小时前
vue种ref跟reactive的区别?
前端·javascript·vue.js·webpack·前端框架·node.js·ecmascript
暮毅11 小时前
10.Node.js连接MongoDb
数据库·mongodb·node.js
~甲壳虫17 小时前
说说webpack中常见的Plugin?解决了什么问题?
前端·webpack·node.js
~甲壳虫17 小时前
说说webpack中常见的Loader?解决了什么问题?
前端·webpack·node.js
~甲壳虫17 小时前
说说webpack proxy工作原理?为什么能解决跨域
前端·webpack·node.js
BearHan18 小时前
Sqlsugar调用Oracle的存储过程
oracle·存储过程·orm
熊的猫18 小时前
JS 中的类型 & 类型判断 & 类型转换
前端·javascript·vue.js·chrome·react.js·前端框架·node.js
前端青山1 天前
Node.js-增强 API 安全性和性能优化
开发语言·前端·javascript·性能优化·前端框架·node.js
GDAL1 天前
npm入门教程1:npm简介
前端·npm·node.js
郑小憨2 天前
Node.js简介以及安装部署 (基础介绍 一)
java·javascript·node.js