NestJS是一个相对较新的 JavaScript Web 框架,使您能够构建企业级的服务器端应用程序。它功能强大,强制执行最佳实践,并使用最新的 JavaScript 功能。它还默认支持 TypeScript 并使用TypeORM,这是一个使用 TypeScript 构建的强大的对象关系管理库。
TypeORM 在 GitHub 上拥有超过29.3k 颗星,是最受欢迎的 Node.js ORM 之一。除了与数据库无关之外,TypeORM 还有一个独特的 API,允许您使用 Active Record 和 Data Mapper 模式以不同的方式访问 SQL 数据库(如 MYSQL 和 PostgreSQL)和 NoSQL 数据库(如 MongoDB)中的数据。
在这篇文章中,我们将学习如何将 TypeORM 与 NestJS 集成,添加数据库驱动程序,并在 NestJS 中使用 TypeORM QueryBuilder 运行基本查询。
要有效地阅读本文,您应该具备:
在您的计算机上安装Node.js v12 LTS 或 Node >v14 — NVM使在不同版本的 Node.js 之间切换变得更加容易
NestJS和JavaScript的基本工作知识
需要复习一些基础知识吗?查看这篇关于使用 NestJS 构建电子商务应用程序的实用文章。
让我们开始吧!
设置 NestJS
生成基本应用设置
使用 SQLite 配置 TypeORM
创建数据库实体
在 NestJS 中使用 TypeORM QueryBuilder 运行基本查询
在带有NestJSJOIN的 TypeORM 查询中使用
使用find选项
使用 QueryBuilderJOIN
设置 NestJS 很简单,有几种方法可以做到,具体取决于您的需要。但是,在本文中,我们将使用 CLI 安装它。
npx @nestjs / cli @9 。0.0新巢-应用
这个命令将搭建 NestJS “Hello, World!” 样板应用程序,因此您可以直接潜入并开始编码。
现在我们已经安装了 NestJS,让我们将 TypeORM 集成到我们的应用程序中。密切关注本节;在开始编写查询之前,您需要正确集成 TypeORM。
在您的终端上运行此命令以安装 TypeORM 和 SQLite3 驱动程序——我们将在本教程中使用 SQLite 来降低安装和设置 MySQL 或 PostgreSQL 数据库的复杂性。
超过 20 万开发人员使用 LogRocket 来创造更好的数字体验了解更多 →
npm install @nestjs / typeorm sqlite3
接下来,让我们使用 NestJS CLI 为我们的查询应用程序的框架生成控制器和服务。运行以下命令生成它并选择 REST API 传输层。
npx @nestjs / cli @9 。0.0 g 资源帖
它将询问您是否要生成 CRUD 入口点。选择是。为您生成所有内容需要一点时间,但这是 NestJS 的有用方面之一。
现在,让我们在文件中配置 TypeORM 。src/app.module.ts
最初,它看起来像这样:
// src/app.module.ts import { Module } from '@nestjs/common' ; 从'./app.controller'导入{ AppController } ;从'./app.service'导入{ AppService } ;从'./posts/posts.module'导入{ PostsModule } ;@Module ({ 导入:[ PostsModule ], 控制器:[ AppController ], 提供者:[ AppService ], })导出类AppModule {}
导入 SQLite 连接选项、TypeORM 模块和 post 实体,如下代码所示:
// src/app.module.ts import { Module } from '@nestjs/common' ; 从'@nestjs/typeorm'导入{ TypeOrmModule } ;从'typeorm/driver/sqlite/SqliteConnectionOptions'导入{ SqliteConnectionOptions } ;从'./app.controller'导入{ AppController } ;从'./app.service'导入{ AppService } ;从'./posts/entities/post.entity'导入{帖子} ; 从'./posts/posts.module'导入{ PostsModule } ; 常量配置:SqliteConnectionOptions = { 类型:“sqlite” , 数据库:“../db” , 实体:[发布], 同步:真} @Module ( { 导入:[ PostsModule , TypeOrmModule .forRoot ( config )], 控制器:[ AppController ], 提供者:[ AppService ],})导出类AppModule {}
现在,让我们完成我们刚刚添加的更新。首先,查看配置对象的形状,我们添加了数据库和实体并同步了数据库。但是,重要的是要记住,在生产环境中同步数据库不是您应该做的事情,因为它可能会导致数据丢失。
// 配置const config : SqliteConnectionOptions = { type : "sqlite" , database : "../db" , entity : [ Post ], synchronize : true // 在生产环境中设置为 false }
因为我们使用的是 SQLite 数据库,所以我们可以使用. 如果它不存在,它将自动为您创建。对于 MySQL 或 PostgreSQL,形状不同,因此请查看文档以了解更多信息。"../db",
不要错过来自 LogRocket 的精选时事通讯The Replay
使用 React 的 useEffect优化应用程序的性能
在多个 Node 版本之间切换
了解如何使用 AnimXYZ 为您的 React 应用程序制作动画
探索 Tauri,一个用于构建二进制文件的新框架
比较NestJS 与 Express.js
发现TypeScript 领域中使用的流行 ORM
实体是数据库模型,在我们的例子中,我们的Post实体有一个 ID 和一个标题,如下面的代码所示:
// src/post/entities/post.entity.ts import { Column , Entity , PrimaryGeneratedColumn } from "typeorm" ; @Entity ()导出类Post { @PrimaryGeneratedColumn () id : number ; @Column () 标题:字符串;}
最后,在通用应用 TypeORM 设置中,让我们将 TypeORM 配置与 NestJS 挂钩。请注意该方法,因为您在设置功能级别配置时可能会看到类似的内容。.forRoot
进口:[ PostsModule ,TypeOrmModule 。forRoot (配置)] ,
在这里,我们将 TypeORM 与 NestJS 挂钩。接下来,让我们将我们的Post功能与 ORM 集成。
导航到该文件并使用以下配置对其进行更新:src/posts/posts.module.ts
// src/posts/posts.module.ts import { Module } from '@nestjs/common' ; 从'./posts.service'导入{ PostsService } ;从'./posts.controller'导入{ PostsController } ;@Module ({ controllers : [ PostsController ], providers : [ PostsService ] })导出类PostsModule {}
接下来,导入 TypeORM,Post实体,并通过设置模块导入的值来更新代码。请注意,我们使用并传入了一组实体,而不是应用级模块配置。[TypeOrmModule.forFeature([Post])]``forFeature
从'@nestjs/common'导入{模块} ;从'./posts.service'导入{ PostsService } ;从'./posts.controller'导入{ PostsController } ;从'@nestjs/typeorm'导入{ TypeOrmModule } ;从'./entities/post.entity'导入{帖子} ;@Module ({ 进口: [ TypeOrmModule . forFeature ([ Post ])], 控制器:[ PostsController ], 提供者:[ PostsService ] })导出类PostsModule {}
有几种方法可以使用 TypeORM 和 NestJS 访问数据库,包括使用 Repository API、Entity Manager API 和使用 DataSource API。
下面是一个快速示例,说明如何使用上述 API 按 ID 获取项目。我已经删除了与本示例无关的大部分代码,但您可以在GitHub 上找到完整的代码。
//src/posts/posts.service.ts @Injectable ()导出类PostsService { 构造函数(@InjectRepository ( Post ) private postRepository : Repository < Post >, @InjectEntityManager () private postManager : EntityManager , @InjectDataSource () private dataSource : DataSource ) { } 异步findOne ( id : number ) { const postWithRepository =等待这个。后存储库。findOneBy ({ id }); const postWithRepositoryQueryBuilder =等待这个。后存储库 。createQueryBuilder (“发布” )。其中(“post.id=:postId” ,{ postId :id })。得到一个() const postWithEntityManager = await this.postManager .createQueryBuilder(Post, "post") .where("post.id= :postId", { postId: id }) .getOne() const postWithDataSource = await this.dataSource .createQueryBuilder() .select("post") .from(Post, "post") .where("post.id= :postId", { postId: id }) .getOne() return { postWithRepository, postWithRepositoryQueryBuilder, postWithEntityManager, postWithDataSource }; } }
如您所见,我们在构造函数中初始化了数据访问层,然后在方法中使用它们。
//src/posts/posts.service.ts ...构造函数( @InjectRepository ( Post ) private postRepository : Repository < Post >, ) { } ...
除此之外,其余代码只是普通的 TypeORM 查询;您可以通过查看他们的文档来更深入地了解 TypeORM 。
上述代码中的所有查询都将返回相同的结果。那么,有几种方法可以实现一个目标,但哪种方法最有效呢?
在处理小型数据集时,这两种方法的表现相似。但是,我发现在处理具有多个关系的大型数据集时,QueryBuilder API 比存储库查询更有效。我相信这是因为QueryBuilder API比Repository API 更接近原始 SQL 查询。
如果您编写的 SQL 查询涉及使用 SQL 从多个表中访问数据,那么您之前可能已经编写过JOIN查询。JOIN查询允许您一次从多个表中查询数据。让我们看一下LEFT JOINTypeORM 中的一个操作。这种类型的查询将返回左表中的所有行和右表中的匹配行。
LEFT JOIN在 TypeORM中执行操作有多种方法。让我们来看看其中的一些:
使用find选项
使用查询构建器
尽管我们的重点是使用 QueryBuilder,但我将向您展示一个使用这两个选项的示例,以便您了解两者之间的差异。
下面我们来看看这个SQLLEFT JOIN操作。我们将其转换为使用find选项和 TypeORM 的 QueryBuilder 方法。
SELECT * FROM "user" LEFT JOIN "courses" "course" ON "course"。“id” = “用户”。"courseId" WHERE "课程"。"name" = 'JavaScript Fundamentals' AND "course"。“长度” = '8 小时'
上面的代码是LEFT JOIN使用 TypeORMfind选项的查询。幸运的是,这很简单,因为 TypeORM 会为您找出最好JOIN的并为您提供适当的结果。现在,让我们使用 TypeORM QueryBuilder 实现上述查询。
常量用户=这个。用户管理器 。createQueryBuilder (用户,“用户” )。leftJoin (“课程” 。“id” ,“课程” )。where ( "course.name = :name" , { name : "JavaScript Fundamentals" }) 。andWhere ( "course.length = :length" , { length : "8 hours" })
使用 QueryBuilder 时,您还可以选择不同类型JOINS的find.
以下是TypeORM 中可用的一些附加功能。JOINS
如果您希望在不影响质量的情况下快速构建可靠的后端,请考虑使用 TypeORM。在本文中,我们学习了如何将 TypeORM QueryBuilder 与 NestJS 集成和使用,但我们只触及了使用 TypeORM 可以做什么的皮毛。查看 TypeORM 文档以了解更多信息。
快乐黑客!
成千上万的工程和产品团队使用LogRocket来减少了解技术和可用性问题的根本原因所需的时间。使用 LogRocket,您将减少与客户来回对话的时间,并消除无休止的故障排除过程。LogRocket 让您可以花更多时间构建新事物,而减少修复错误的时间。