返回

TypeORM 动态建表:按需创建实体表方案

mysql

TypeORM 动态实体表创建方案

在项目开发中,我们经常遇到根据不同条件,只针对特定实体创建数据库表的需求。TypeORM 默认会基于所有实体生成表结构,当项目规模增大,这种做法可能会带来一些问题,比如数据隔离和性能问题。本文探讨在 TypeORM 中,如何基于选定实体而非全部实体来创建表结构。

问题分析

通常,我们使用 TypeORM 时,配置数据源 DataSource 时会引入所有实体类,启动同步后,TypeORM 会自动为所有实体创建表。这种机制对于快速启动项目十分便利,但在多租户或拥有复杂权限控制的系统中,这种方式就不够灵活了。我们可能希望根据例如租户 ID,环境设置或其他条件,动态地决定哪些实体需要生成表。因此,问题转化为:如何在 TypeORM 中,按需选择一部分实体来创建表?

解决方案一:entities 属性动态配置

DataSource 构造函数允许你配置 entities 属性。此属性可以接收实体类的数组,用来指定哪些实体应该用于数据库表同步。 我们可以利用这一点实现动态选择实体。

实现步骤:

  1. 定义条件判断逻辑: 编写函数或者方法来评估你的条件,返回一个包含目标实体类的数组。
  2. 动态设置 entities : 使用评估逻辑返回的数组动态地配置数据源的 entities 属性。
  3. 执行同步: 当数据源建立连接并执行表同步时,TypeORM只会针对在 entities 数组中指定的实体类创建对应的数据库表。

代码示例:

import { DataSource } from "typeorm";
import { User } from "./entities/User";
import { Product } from "./entities/Product";
import { Order } from "./entities/Order";
//...其他实体

const getEntitiesBasedOnInstitute = (instituteId: string) => {
  if (instituteId === "xyz") {
    return [User, Product, Order];
    // 返回所有实体类
  } else if (instituteId === "abc") {
    return [User, Order];
    //返回指定部分实体类
  } else {
      return [] ;// 或返回默认实体类列表
  }
};

const instituteId = "abc"; // 根据不同实例修改此变量

const selectedEntities = getEntitiesBasedOnInstitute(instituteId);

const AppDataSource = new DataSource({
  type: "mysql",
  host: "localhost",
  port: 3306,
  username: "root",
  password: "password",
  database: "mydb",
  entities: selectedEntities, //  使用动态获取的实体
  synchronize: true,
});

AppDataSource.initialize()
    .then(() => {
        console.log("Data Source has been initialized!");
    })
    .catch((err) => {
        console.error("Error during Data Source initialization:", err);
});

操作步骤:

  1. 根据你的实体结构,替换上述示例代码中的 User, Product, 和 Order
  2. 根据实际业务修改 getEntitiesBasedOnInstitute 函数的逻辑,让它可以基于实际需求返回正确的实体列表。
  3. 调整数据库配置,使用真实的数据库连接参数。
  4. 运行程序, TypeORM 将仅创建返回的实体表。

安全提示:
避免硬编码任何敏感信息(例如数据库密码)。可以将这些值放在环境变量中,并在配置中读取这些环境变量。

解决方案二:基于 CLI 参数和 .env 配置

另外一种实现按需创建表的方法是借助 TypeORM CLI 工具和 .env 文件。这种方法更适用于通过命令行或脚本启动应用时的情况,增加了灵活性。

实现步骤:

  1. 创建 .env 文件 : 在项目根目录下创建 .env 文件。
  2. 添加环境变量 : 在此文件中, 定义环境变量指定所需使用的实体文件路径,例如 TYPEORM_ENTITIES_DIR=./src/entities/user.ts,./src/entities/order.ts.
  3. 动态配置 CLI 命令: 在运行 typeorm migration:run 时, typeorm 将读取此变量,根据指定的实体列表执行同步。
  4. 执行同步 : 通过命令行启动 typeorm schema:sync, 它将会根据 .env 中配置的实体进行创建表。

.env 文件示例:

TYPEORM_ENTITIES_DIR=./src/entities/User.ts,./src/entities/Order.ts
# 或者配置所有目录 TYPEORM_ENTITIES_DIR=./src/entities/**/*.ts

命令行指令:

typeorm schema:sync

操作步骤:

  1. 修改 env 文件,指定你需要的实体文件列表或者通配符路径。
  2. 使用 schema:sync 命令创建数据表。

原理说明:
此方案利用 typeorm schema:sync 命令结合 TYPEORM_ENTITIES_DIR 环境变量来达到动态选择实体的效果。TypeORM CLI 工具在运行时会读取此环境变量并按照其指定的路径载入实体,然后只针对这些实体执行表结构的创建。通过在启动时指定环境变量,我们可以实现更灵活的部署和维护流程。

安全提示: .env 文件包含敏感信息,确保此文件不被公开提交到版本控制系统。另外,使用 --dotenv 参数或环境变量 DOTENV_CONFIG_PATH 指定自定义 .env 文件路径可以提高应用环境管理的灵活性。

这些方法为基于特定条件动态创建 TypeORM 表结构提供了实用方案。根据项目需要和团队习惯,可以选择更合适的一种或多种方法来优化数据库表的管理。