如何使用 TypeORM 种子数据库让我们开始编码

2025-06-05

如何使用 TypeORM 种子来为数据库播种

让我们开始编码

概述

除了在应用程序原型设计过程中提供极大的便利之外,它还能在生产环境中为我们带来诸多好处。也就是说,它能够帮助我们从构思过程、应用程序创建到生产环境。

您可能已经从文章标题中注意到了这一点,或者我决定创建一篇简单的文章,其中我们使用最流行的 ORM 之一,并且我们将为我们的数据库播种。

数据库播种可以在不同的环境中完成,从插入随机批次以便我们可以更快地测试我们的应用程序(这有助于我们的开发经验),但我们也可以定义一个对象数组,这些对象可以是数据。管理员帐户或仅仅是需要在生产环境中使用的数据。

在今天的示例中,我将解释如何将随机数据插入数据库,以及如何在它们之间建立关系。最终,我们将拥有一个只有两个端点的 API:一个用于获取所有用户及其文章,另一个用于获取所有文章及其作者。

我还想补充一点,本文不会讲解如何使用 Express、TypeORM 和 TypeScript 创建 API。我只会讲解如何在现有 API 中实现数据库的种子填充。如果您想访问包含本文最终成果的 GitHub 仓库,请点击此处

让我们开始编码

在我们的项目的根目录中(package.json 所在的位置),我们将安装以下依赖项:

npm install typeorm-seeding faker --save
npm install @types/faker --save-dev
Enter fullscreen mode Exit fullscreen mode

现在我将解释我认为关于我们将要使用的库( typeorm-seeding )的两件基本的事情

我首先要讲的是工厂。基本上,我们会为应用程序中的每个实体定义一个工厂,它负责生成填充应用程序的数据。这些数据分别对应于我们在实体中定义的属性。

因此,我们假设这些是您的实体:

// @/src/db/entities/user.ts
import {
  Entity,
  PrimaryGeneratedColumn,
  Column,
  OneToMany,
  BaseEntity,
} from "typeorm";
import { Post } from "./post";

@Entity()
export class User extends BaseEntity {
  @PrimaryGeneratedColumn()
  id!: number;

  @Column()
  name!: string;

  @OneToMany(() => Post, (post) => post.user)
  posts?: Post[];
}
Enter fullscreen mode Exit fullscreen mode
// @/src/db/entities/post.ts
import {
  Entity,
  PrimaryGeneratedColumn,
  Column,
  ManyToOne,
  BaseEntity,
} from "typeorm";
import { User } from "./user";

@Entity()
export class Post extends BaseEntity {
  @PrimaryGeneratedColumn()
  id!: number;

  @Column()
  title!: string;

  @Column()
  description!: string;

  @Column({ type: "boolean", default: false })
  isPublished!: boolean;

  @ManyToOne(() => User, (user) => user.posts)
  user!: User;
}
Enter fullscreen mode Exit fullscreen mode

对于用户实体,我们只需要生成与该工厂对应的用户名:

// @/src/db/seeding/factories/user.factory.ts
import * as Faker from "faker";
import { define } from "typeorm-seeding";

import { User } from "../../entities";

define(User, (faker: typeof Faker) => {
  const user = new User();
  const firstName = faker.name.firstName();
  const lastName = faker.name.lastName();
  user.name = `${firstName} ${lastName}`;
  return user;
});
Enter fullscreen mode Exit fullscreen mode

就这篇文章而言,它应该是这样的:

// @/src/db/seeding/factories/post.factory.ts
import * as Faker from "faker";
import { define } from "typeorm-seeding";

import { Post } from "../../entities";

define(Post, (faker: typeof Faker) => {
  const post = new Post();
  post.title = faker.lorem.words(8);
  post.description = faker.lorem.paragraph(6);
  post.isPublished = faker.random.boolean();
  return post;
});
Enter fullscreen mode Exit fullscreen mode

现在我们的工厂已经定义好了,只要我们定义了想要创建的用户或文章的数量,工厂就会在每个属性中生成随机值。

现在我们可以转到 Seeder,seeder 是一个用于执行数据库播种的类,在这里我希望您小心名称,因为种子的名称对应于类的名称(而不是文件的名称)。

Seeder 的样板如下:

// @/src/db/seeding/seeds/initialSeed.ts
import { Factory, Seeder } from "typeorm-seeding";
import { Connection } from "typeorm";

// ...

export default class InitialDatabaseSeed implements Seeder {
  public async run(factory: Factory, connection: Connection): Promise<void> {
    // ...
  }
}
Enter fullscreen mode Exit fullscreen mode

我们首先需要做的是导入我们要播种的实体。

// @/src/db/seeding/seeds/initialSeed.ts
import { Factory, Seeder } from "typeorm-seeding";
import { Connection } from "typeorm";

import { User, Post } from "../../entities";

export default class InitialDatabaseSeed implements Seeder {
  public async run(factory: Factory, connection: Connection): Promise<void> {
    // ...
  }
}
Enter fullscreen mode Exit fullscreen mode

现在让我们先为用户表播种,并定义我们想在表中总共插入 15 个用户。

// @/src/db/seeding/seeds/initialSeed.ts
import { Factory, Seeder } from "typeorm-seeding";
import { Connection } from "typeorm";

import { User, Post } from "../../entities";

export default class InitialDatabaseSeed implements Seeder {
  public async run(factory: Factory, connection: Connection): Promise<void> {
    const users = await factory(User)().createMany(15);

    // ...
  }
}
Enter fullscreen mode Exit fullscreen mode

创建用户后,我们现在要生成文章。不过,这次除了定义要生成的文章数量外,我们还需要传递必须是文章作者的用户。在本例中,我们必须以随机方式分配作者。像这样:

// @/src/db/seeding/seeds/initialSeed.ts
import { Factory, Seeder } from "typeorm-seeding";
import { Connection } from "typeorm";

import { User, Post } from "../../entities";

export default class InitialDatabaseSeed implements Seeder {
  public async run(factory: Factory, connection: Connection): Promise<void> {
    const users = await factory(User)().createMany(15);

    await factory(Post)()
      .map(async (post) => {
        post.user = users[Math.floor(Math.random() * users.length)];
        return post;
      })
      .createMany(100);
  }
}
Enter fullscreen mode Exit fullscreen mode

定义工厂并创建播种机后,下一步就是在 TypeORM 配置中定义工厂和播种机所在的目录。

// @/ormconfig.ts
import { User, Post } from "./src/db/entities";

export default {
  name: "default",
  type: "sqlite",
  database: "src/db/dev.db",
  entities: [User, Post],
  synchronize: true,
  logging: false,
  // These two lines have been added:
  seeds: ["src/db/seeding/seeds/**/*{.ts,.js}"],
  factories: ["src/db/seeding/factories/**/*{.ts,.js}"],
};
Enter fullscreen mode Exit fullscreen mode

最后,只需转到我们的package.json并创建负责播种数据库的脚本。

// @/package.json
{
  // ...
  "scripts": {
    // ...
    "db:seed": "ts-node ./node_modules/typeorm-seeding/dist/cli.js seed"
  },
  // ...
}
Enter fullscreen mode Exit fullscreen mode

不要忘记运行您的 API 进程并运行命令npm run db:seed来为您的数据库提供种子。

结论

一如既往,希望你觉得这篇文章有趣。如果你发现本文有任何错误,请在评论区指出。🧑🏻‍💻

祝你度过美好的一天!👋 🌱

文章来源:https://dev.to/franciscomendes10866/how-to-seed-database-using-typeorm-seeding-4kd5
PREV
如何在 Node.js 中使用 ZeroMQ 发布/订阅模式
NEXT
如何在 React 中创建搜索栏 让我们来编写代码