乐闻世界logo
搜索文章和话题
基于 NestJS 操作 TypeORM 中的一对多 OneToMany

基于 NestJS 操作 TypeORM 中的一对多 OneToMany

乐闻的头像
乐闻

2024年01月01日 10:37· 阅读 2041

前言

TypeORM 是一个在 TypeScript 和 JavaScript (ES7, ES6, ES5) 中提供了许多开箱即用特性的 ORM,它能够改善我们处理数据库操作的效率与可维护性。在复杂的应用开发过程中,数据间的关系处理显得尤其重要。今天我们将在 NestJS 中探索 TypeORM 的 OneToMany(一对多)关系,这是一种常见且强大的数据模型关系。在建立应用程序时,我们通常需要处理大量的增删查改(CRUD)操作,而 OneToMany 关系的巧妙应用能够让这些操作变得更为简洁、优雅。

使用步骤

一、安装依赖

首先需要在我们的 NestJS 应用中安装并设置 TypeORM。在你的项目根目录下执行以下命令:

shell
npm install --save @nestjs/typeorm typeorm

二、模块初始化

在项目的 app.module.ts 文件中进行 TypeORM 的设置。

typescript
import { Module } from '@nestjs/common'; import { TypeOrmModule } from '@nestjs/typeorm'; import { AppController } from './app.controller'; import { AppService } from './app.service'; import { Author } from './author.entity'; import { Post } from './post.entity'; @Module({ imports: [ TypeOrmModule.forRoot({ type: 'postgres', host: 'localhost', port: 5432, username: 'test', password: 'test', database: 'test', entities: [Author, Post], synchronize: true, }), ], controllers: [AppController], providers: [AppService], }) export class AppModule {}

三、建立一对多的实体关系

我们创建**作者 文章这两个实体。先建立 作者实体,再设定 文章实体**。

Author

typescript
import {Entity, Column, OneToMany, PrimaryGeneratedColumn} from 'typeorm'; import { Post } from './post.entity'; @Entity() export class Author { @PrimaryGeneratedColumn() id: number; @Column() name: string; @OneToMany((type) => Post, (post) => post.author) posts: Post[]; }

Post

typescript
import {Entity, PrimaryGeneratedColumn, Column, ManyToOne} from 'typeorm'; import { Author } from './author.entity'; @Entity() export class Post { @PrimaryGeneratedColumn() id: number; @Column() title: string; @ManyToOne((type) => Author, (author) => author.posts) author: Author; }

四、实现对应的服务层

为了创建作者和他的文章,我们需要创建一个服务。服务通过依赖注入来定义在各个模块之间的关系,你还需要记住的一点是:在 NestJS 中,你需要使用 Repository 来操作数据库。而 InjectRepository() 装饰器会帮助我们自动创建并注册这个 Repository。

Author Service

typescript
import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { Repository } from 'typeorm'; import { Author } from './author.entity'; import { Post } from './post.entity'; @Injectable() export class AuthorService { constructor( @InjectRepository(Author) private authorsRepository: Repository<Author>, @InjectRepository(Post) private postsRepository: Repository<Post>, ) {} async createAuthorWithPosts() { const author = this.authorsRepository.create({ name: 'John Doe' }); const post1 = this.postsRepository.create({ title: 'Post #1', author, }); const post2 = this.postsRepository.create({ title: 'Post #2', author, }); author.posts = [post1, post2]; await this.authorsRepository.save(author); // ... } }

五、一对多的增删改查操作

  • 新增 Create

    在 AuthorService 中,我们已经创建了 createAuthorWithPosts 方法,可以同时创建作者和对应的文章:

    typescript
    async createAuthorWithPosts() { const author = this.authorsRepository.create({ name: 'John Doe' }); const post1 = this.postsRepository.create({ title: 'Post #1', author, }); const post2 = this.postsRepository.create({ title: 'Post #2', author, }); author.posts = [post1, post2]; await this.authorsRepository.save(author); }
  • 删除 Remove

    删除某一篇文章,可以通过 remove 方法来达成:

    typescript
    async deletePost(postId: number) { let toDelete = await this.postsRepository.findOne(postId); let deleted = false; if (toDelete) { await this.postsRepository.remove(toDelete); deleted = true; } return { deleted }; }
  • 修改 Update

    假设我们要更新某一篇文章的信息,可以通过 update 方法来操作:

    typescript
    async updatePost(postId: number, updatedTitle: string) { let toUpdate = await this.postsRepository.findOne(postId); let updated = false; if (toUpdate) { toUpdate.title = updatedTitle; await this.postsRepository.save(toUpdate); updated = true } return { updated }; }
  • 查询 Search

    例如我们想要查找一个作者所有的文章,可以创建如下方法:

    typescript
    async findPostsByAuthor(authorId: number) { return this.postsRepository.createQueryBuilder("post") .innerJoinAndSelect("post.author", "author") .where("author.id = :authorId", { authorId }) .getMany(); }
  • 列表查询

    假设我们想要查询所有的作者列表,可以通过 find 方法实现:

    typescript
    async findAllAuthors() { return await this.authorsRepository.find(); }

进阶操作

一、分页查询

当你的数据太多,你可能需要进行分页查询。我们可以使用 take 和 skip 方法进行分页查询。

下面这个方法展示了如何获取第二页的作者,每页有5个作者:

typescript
async findAuthorsPagination(page: number) { return await this.authorsRepository.find({ take: 5, skip: 5 * (page - 1), }); }

在这个方法中, take 表示要获取的条数,skip 表示要跳过的条数。

二、关联查询

在我们有了OneToMany的关系后, 假设我们需要获取包含了一个作者的所有文章的信息, 那我们就需要做一个关联查询:

typescript
async findAuthorAndPosts(authorId: number) { return this.authorsRepository.findOne(authorId, { relations: ["posts"] }); }

这个 findOne 方法会返回一个 Author 对象,该对象包含一个 Post 对象的数组,表示该作者写的所有文章。

总结

在使用 NestJS 和 TypeORM 进行开发时,我们已经掌握了 OneToMany(一对多)关系的设定、如何进行基础的 CRUD(增删查改)操作,还了解了列表查询、分页查询及关联查询的实现方式。最后,不要忘记,TypeORM 的 OneToMany 关系默认情况下是懒加载的,使得我们在需要时才去加载关联数据,提升了程序的运行效率。借助 NestJS 和 TypeORM,我们能够轻松处理复杂的数据关联关系,提升开发效率。

标签: