最近在學習NestJs,可是不從實際需求出發,沒有項目的依託,感受老是個入門而已,只有在解決一個個項目上的問題才能進一步加深和鞏固所學知識,故想將搭建一個博客後臺系統的需求爲出發點,鞏固所學知識,同時也做爲學習新知識、難題解決及注意事項的記錄。mysql
yarn add @nestjs/typeorm typeorm mysql
在app.modules中用TypeOrmModule實現數據庫鏈接
// src/app.module.ts import { Module } from '@nestjs/common'; import { AppController } from './app.controller'; import { AppService } from './app.service'; import { TypeOrmModule } from '@nestjs/typeorm'; @Module({ imports: [ TypeOrmModule.forRootAsync({ useFactory: () => ({ type: 'mysql', host: 'localhost', port: 3306, username: 'root', password: '', database: 'blogs', timezone: 'UTC', charset: 'utf8mb4', entities: ['./**/*.entity.js'], synchronize: true, logging: true, })}), ], controllers: [AppController], providers: [AppService], }) export class AppModule {}
entity(實體對象)映射數據庫中的表,entity中的Column與表中的字段相對應
// src/entities/article.entity.ts import { Entity, Column, PrimaryGeneratedColumn, CreateDateColumn, UpdateDateColumn, DeleteDateColumn } from 'typeorm'; @Entity('article') export class ArticleEntity { @PrimaryGeneratedColumn({ type: 'int', comment: '主鍵id', }) id: number; @Column('varchar', { nullable: false, comment: '文章標題', }) title: string; @Column('varchar', { nullable: false, comment: '文章內容', }) content: string; @Column({ nullable: false, name: 'category_id', comment: '文章類別', }) categoryID: string; @Column('varchar', { nullable: true, comment: '文章簡介', }) intro: string; @Column('varchar', { nullable: true, comment: '文章封面', }) cover: string; @Column('varchar', { nullable: true, comment: '文章標籤', }) tags: string; @Column('enum', { nullable: false, default: 0, enum: [0, 1, 2], comment: '文章狀態,0爲編輯中,1爲已發佈,2爲不可用', }) status: number; @CreateDateColumn({ type: 'timestamp', name: 'created_at', comment: '建立時間', }) createdAt: Date; @UpdateDateColumn({ type: 'timestamp', name: 'updated_at', comment: '最後更新時間', }) updatedAt: Date; @DeleteDateColumn({ type: 'timestamp', name: 'delete_at', comment: '刪除', }) deleteAt: Date; }
// src/entities/article-category.entity.ts import { Entity, Column, PrimaryGeneratedColumn, CreateDateColumn, UpdateDateColumn, DeleteDateColumn } from 'typeorm'; @Entity('article_category') export class ArticleCategoryEntity { @PrimaryGeneratedColumn({ type: 'int', comment: '主鍵id', }) id: number; @Column('varchar', { nullable: false, unique: true, name: 'category_name', comment: '文章類別名稱', }) categoryName: string; @CreateDateColumn({ type: 'timestamp', name: 'created_at', comment: '建立時間', }) createdAt: Date; @UpdateDateColumn({ type: 'timestamp', name: 'updated_at', comment: '最後更新時間', }) updatedAt: Date; @DeleteDateColumn({ type: 'timestamp', name: 'delete_at', comment: '刪除', }) deleteAt: Date; }
Tips:entity要放在/src/entities目錄下,才能在dist目錄下生成.entity.js格式的文件,直接加載.entity.ts文件則會報語法錯誤,以前試過新建libs,而後將數據庫模塊放到libs下,但願將數據庫這部分獨立出來,方便維護;不過發現最後編譯只會在dist生成一個main.js文件,缺乏.entity.js,查看main.js內容發現*.entity.ts編譯的結果也直接放入main.js中。sql
EntityManager: 像放一個實體存儲庫的集合的地方,你能夠管理(insert, update, delete, load等)任何實體;能夠經過getManager()或Connection訪問實體管理器。
Repository: 像EntityManager同樣,但其操做僅限於具體實體;能夠經過getRepository(Entity),Connection#getRepository訪問存儲庫。
數據庫
下面經過Repository提供的API來實現對數據庫的增刪改查,以及左聯查詢api
// src/service/article/article.service.ts import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { ArticleCategoryEntity } from 'src/entities/article-category.entity'; import { ArticleEntity } from 'src/entities/article.entity'; import { Repository, createQueryBuilder, getConnection, getRepository } from 'typeorm'; @Injectable() export class ArticleService { constructor( @InjectRepository(ArticleCategoryEntity) private readonly articleCategoryRepo: Repository<ArticleCategoryEntity>, @InjectRepository(ArticleEntity) private readonly articleRepo: Repository<ArticleEntity>, ) { } /** * 獲取文章分類 */ getArticleCate() { return this.articleCategoryRepo.find(); } /** * 建立文章分類 * @param body */ createArticleCate(body): Promise<any> { const userEntity = this.articleCategoryRepo.create(body); return this.articleCategoryRepo.save(userEntity); } /** * 刪除文章分類 * @param id 文章分類ID */ delArticleCate(id): Promise<any> { return this.articleCategoryRepo.delete(id); } /** * 獲取文章 * @param id 文章ID */ getArticle(id) { // 利用leftJoinAndMapOne方法進行左聯查詢 // 兩個未關聯的實體,經過getRawMany獲取原始查詢數據 if (id) { return createQueryBuilder(ArticleEntity, 'article') .leftJoinAndMapOne('article.cate_name', ArticleCategoryEntity, 'cate', 'cate.id = article.category_id') .where('article.id = :id', { id }) .select(['article.*', 'cate.category_name']) .getRawMany(); // 得到原始結果 } else { return createQueryBuilder(ArticleEntity, 'article') .leftJoinAndMapOne('article.cate_name', ArticleCategoryEntity, 'cate', 'cate.id = article.category_id') .getRawMany(); // 得到原始結果 } } /** * 建立文章 * @param body */ createArticle(body) { const articleEntity = this.articleRepo.create(body); return this.articleRepo.save(articleEntity); } /** * 更新文章 * @param id * @param body */ updateArticle(id, body) { return this.articleRepo.update(id, body); } /** * 刪除文章 * @param id 文章ID */ delArticle(id) { return this.articleRepo.delete(id); } }