前端 | 嘿,Nest.js實戰開發系列之使用TypeORM操作數據庫
寫在前面
在上一篇文章《【前端】嘿,Nest.js實戰開發系列 01 ── Nest.js初體驗》中介紹了如何上手nest.js,同時詳細介紹了如何進行項目創建、路由訪問和創建模塊,這些都是項目實踐的基礎。隨著項目的推進,我們就要考慮如何實現數據庫的連接和使用,這樣可以用來實現前后端數據交互的數據存儲。
環境準備:
- Mysql 5.7
- TypeORM 0.2.34
TypeORM集成
在Nest.js中可以使用任意數據庫,且內部集成提供了TypeORM 和 Sequelize ,開箱即用@nestjs/typeorm和@nestjs/sequelize包。Nest 使用TypeORM,因為它是可用于 TypeScript 的最成熟的對象關系映射器 (ORM)。由于它是用 TypeScript 編寫的,因此它可以很好地與 Nest 框架集成。
要開始使用它,我們首先安裝所需的依賴項。在命令行中輸入:
- $ npm install --save @nestjs/typeorm typeorm mysql2
安裝完畢后,可以將TypeOrmModule導入根目錄AppModule。
app.module.ts
- import { Module } from '@nestjs/common';
- import { TypeOrmModule } from '@nestjs/typeorm';
- @Module({
- imports: [
- TypeOrmModule.forRoot({
- type: 'mysql',
- host: 'localhost',
- port: 3306,
- username: 'root',
- password: 'root',
- database: 'test',
- entities: [],
- synchronize: true,
- }),
- ],
- })
- export class AppModule {}
切記:synchronize: true不應在生產中使用設置- 否則您可能會丟失生產數據。
該forRoot()方法支持TypeORM包中的createConnection()函數公開的所有配置屬性。此外,還有幾個額外的配置屬性如下所述。
當然,也可以在根目錄下創建ormconfig.json文件,在文件中進行數據庫信息的設置。
ormconfig.json
- {
- "type": "mysql",
- "host": "localhost",
- "port": 3306,
- "username": "root",
- "password": "root",
- "database": "test",
- "entities": ["dist/**/*.entity{.ts,.js}"],
- "synchronize": true
- }
然后,我們可以在forRoot()沒有任何選項的情況下調用:
app.module.ts
- import { Module } from '@nestjs/common';
- import { TypeOrmModule } from '@nestjs/typeorm';
- @Module({
- imports: [TypeOrmModule.forRoot()],
- })
- export class AppModule {}
注意:靜態 glob 路徑(例如,dist/**/*.entity{ .ts,.js})將無法與webpack正常工作。
其實,ormconfig.json文件是由typeorm庫加載的,因此不會應用額外的屬性設置。TypeORM 提供了getConnectionOptions從ormconfig文件或環境變量中讀取連接選項的函數。
完成以上操作后,TypeORMConnection和EntityManager對象將可用于在整個項目中注入(無需導入任何模塊)。
app.module.ts
- import { TypeOrmModule } from '@nestjs/typeorm';
- import { Connection } from "typeorm";
- import { UsersModule } from './users/users.module';
- @Module({
- imports: [
- TypeOrmModule.forRoot(),
- UsersModule
- ],
- controllers: [AppController],
- providers: [AppService],
- })
- export class AppModule {
- constructor(private connection: Connection){}
- }
存儲庫模式
TypeORM支持存儲庫設計模式,因此每個實體都有自己的存儲庫。這些存儲庫可以從數據庫連接中獲得。
下面創建一個用戶實體,users.entity.ts在users目錄下,
users.entity.ts
- import {Entity, PrimaryGeneratedColumn, Column, BeforeInsert, JoinTable, ManyToMany, OneToMany} from 'typeorm';
- import { IsEmail } from 'class-validator';
- import * as argon2 from 'argon2';
- import { ArticleEntity } from '../article/article.entity';
- @Entity('user')
- export class UserEntity {
- @PrimaryGeneratedColumn()
- id: number;
- @Column()
- username: string;
- @Column()
- @IsEmail()
- email: string;
- @Column({default: ''})
- bio: string;
- @Column({default: ''})
- image: string;
- @Column()
- password: string;
- @BeforeInsert()
- async hashPassword() {
- this.password = await argon2.hash(this.password);
- }
- @ManyToMany(type => ArticleEntity)
- @JoinTable()
- favorites: ArticleEntity[];
- @OneToMany(type => ArticleEntity, article => article.author)
- articles: ArticleEntity[];
- }
現在開始使用Users實體,只需要在users.module.ts文件中通過entities模塊forFeature()方法選項中的數組來進行導入。
users.module.ts
- import { Module } from '@nestjs/common';
- import { UsersController } from './users.controller';
- import { UsersService } from './users.service';
- import {UsersEntity} from "./users.entity";
- import { TypeOrmModule } from '@nestjs/typeorm';
- @Module({
- imports: [TypeOrmModule.forFeature([UsersEntity])],
- providers: [UsersService],
- controllers: [
- UsersController
- ],
- exports: [UsersService]
- })
- export class UsersModule {}
此模塊使用forFeature()來定義在當前范圍內注冊了那些存儲庫,此時將可以使用裝飾器將UsersRepository注入到`UsersService @InjectRepository().
users.service.ts
- import {Get, Post, Body, Put, Delete, Query, Param, Controller} from '@nestjs/common';
- import { UsersService } from './users.service';
- @Controller('user')
- export class UsersController {
- constructor(private readonly usersService: UsersService){}
- // 查找指定用戶
- @Get("find/:id")
- async findById(@Query("id") id: number){
- return this.usersService.findById(id);
- }
- }
數據表間的關系
關系是在兩個或多個表之間建立的關聯,是基于每張表的公共字段,通常是主鍵和外鍵。
數據表之間有三種關系:
因此,在實體中定義關系可以使用相應的裝飾器。
測試代碼
users.controller.ts
- import {Get, Post, Body, Put, Delete, Query, Param, Controller} from '@nestjs/common';
- import { UsersService } from './users.service';
- @Controller('user')
- export class UsersController {
- constructor(private readonly usersService: UsersService){}
- // 查找指定用戶
- @Get("find/:id")
- async findById(@Query("id") id: number){
- return this.usersService.findById(id);
- }
當我們運行代碼時,數據庫自動生成了users表。
而當我們在postman向服務器請求指定id的用戶信息時,請求結果如下所示:
后臺顯示結果如下:
我們看到以上代碼測試是正確的。
小結
本篇文章介紹了mysql和typeorm之間的關系,typeorm的配置,nest是如何通過typeorm連接數據庫,以及簡單的用戶表數據查詢。
其實筆者之前也用過 Sequelize ,現在想要嘗試typeorm和nest的搭配,所以文章寫的有些亂,建議諸位多加查看官方文檔:《Nest官方文檔》和《Typeorm官方文檔》