基于 Nest.js+TypeORM 实战,项目已开源,推荐!

本文是Nest.js实战系列的一部分,介绍了如何使用TypeORM处理一对一、一对多和多对多的关系,包括实体定义、授权守卫实现、文章接口的创建、多表查询以及文件上传到腾讯云COS。文章强调了接口实现中的关键点,如文章状态处理、权限校验和联表查询的不同方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

大厂技术  高级前端  Node进阶

点击上方 程序员成长指北,关注公众号

回复1,加入高级Node交流群

考拉🐨 的 Nest.js 系列文章(系列会持续更新):

学完这篇 Nest.js 实战,还没入门的来锤我!(长文预警)

Nest.js 实战系列第二篇-实现注册、扫码登陆、jwt认证等

这篇文章是上篇实现登录、注册的后续, 本来是和上一篇文章写在一起的, 考虑篇幅问题,就拆了一个下篇出来。

文章主要内容:

331715202d3b080baad3dd093d64e659.png

有的小伙伴可能觉得文章不就增删改查嘛,没什么好写的吧!

其实在我整体写下来,觉得文章模块还是涉及到很多知识点的,比如分类表与文章表的一对多以及文章表与标签表多对多处理、文件上传等,还有一些实现的小细节:关于文章摘要的提取方式,Markdownhtml等,都会在这篇文章中给大家介绍清楚。

前置说明

首先我们说一下文章设计的需求,文章基本信息:标题、封面、摘要、阅读量、点赞量等;文章有分类,一篇只能选择一个分类;一篇文章可以选择多个标签,文章的状态分为草稿和已发布,考虑到后期文章的展示,还给文章设置了推荐标识。

数据表关系

前面文章中已经说了TypeORM建表时,是通过@Entity()装饰的class 映射为数据表, 所以实体中的关系也就是表关系。接下来探索一下如何用TypeORM创建一对一、一对多和多对多的关系。

一对一

一对一指的是表中一条数据仅关联另外一个表中的另一条数据。例如用户表和用户档案表, 一个用户只有一份档案。我们在TypeORM中如何实现user表和info之间这种对一对的关系呢?

// user.entity.ts

@Entity('user')
export class UserEntity {
  @PrimaryGeneratedColumn()
  id: number;

  @Column()
  username: string;

  @OneToOne(type =>InfoEntity, info => info.user)
  @JoinColumn()
  info: InformationEntity;
}

infoInfoEntity类型的,但是存入在数据库中类型却是 info.id 的类型。从上面代码可以看出, 是通过@OneToOne装饰器来修饰的, 在装饰器中需要指定对方entity的类型,以及指定对方entity的外键。

@JoinColumn 必须在且只在关系的一侧的外键上, 你设置@JoinColumn的哪一方,哪一方的表将包含一个relation id和目标实体表的外键。记住,不能同时在二者entity中。

看一下info实体如何实现:

@Entity('info')
export class InfoEntity {
  @PrimaryGeneratedColumn()
  id: number;

  @Column()
  idcard: string;
  
  @Column()
  gender: string;
  ...
  @OneToOne(type =>UserEntity, user => user.info)
  user: UserEntity;
}

以上两个实体映射的数据表如下:

|                       user表                                         |
+--------+--------------+-----+-----------------+----------------------+
| Field  | Type         | Key | Default         | Extra                |
+--------+--------------+-----+-----------------+----------------------+
| id     | int(11)      | PRI | NULL            | auto_increment       |
| name   | varchar(255) |     | NULL            |                      |
| infoId | int(11)      | MUL | NULL            |                      |
+--------+--------------+-----+-----------------+----------------------+

|                       info表                                         |
+--------+--------------+-----+-----------------+----------------------+
| Field  | Type         | Key | Default         | Extra                |
+--------+--------------+-----+-----------------+----------------------+
| id     | int(11)      | PRI | NULL            | auto_increment       |
| idcard | varchar(255) |     | NULL            |                      |
| gender | varchar(255) |     | NULL            |                      |
+--------+--------------+-----+-----------------+----------------------+

生成的从数据表可以看出,默认生成的"relation id 格式为xxId, 如果你是数据表中希望对其进行重名名, 可以通过@JoinColumn配置,在一对多例子中会实践一下。

一对多

在一对多关系中,表A中的一条记录,可以关联表B中的一条或多条记录。比如:每一个文章分类都可以对应多篇文章,反过来一篇文章只能属于一个分类,这种文章表和分类表的关系就是一对多的关系。

同样我们用代码看看TypeOrm中如何实现这种关系的:

// category.entity.ts
import {PostEntity} from "../../post/post.entity"
@Entity('category')
export class CategoryEntity {
  @PrimaryGeneratedColumn()
  id: number;

  @Column()
  name: string;

  @OneToMany(() => PostEntity, post => post.category)
  post: PostEntity[];
}

@OneToMany添加到post属性中, 并且在@OneToMany中指定对方的类型为PostEntity, 接下来定义文章实体:

// posts.entity.ts
...
import { CategoryEntity } from './../category/entities/category.entity';

@Entity('post')
export class PostsEntity {
 @PrimaryGeneratedColumn()
 id: number;
 
 @Column({ length: 50 })
 title: string;
 
 ...
  // 分类
 @Exclude()
 @ManyToOne(() => CategoryEntity, (category) => category.posts)
 @JoinColumn({name: "category_id"})
 category: CategoryEntity;
}

@ JoinColumn不仅定义了关系的哪一侧包含带有外键的连接列,还允许自定义连接列名和引用的列名。上边文章entity中,就自定义了列名为category_id, 如果不自定义, 默认生成的列名为categoryId

TypeORM在处理“一对多”的关系时, 将的主键作为的外键,即@ManyToOne装饰的属性;这样建表时有最少的数据表操作代价,避免数据冗余,提高效率, 上面的实体关系会生成以下表:

|                       category表                                         |
+--------+--------------+-----+-----------------+----------------------+
| Field  | Type         | Key | Default         | Extra                |
+--------+--------------+-----+-----------------+----------------------+
| id     | int(11)      | PRI | NULL            | auto_increment       |
| name   | varchar(255) |     | NULL            |                      |
+--------+--------------+-----+-----------------+----------------------+

|                       post表                                         |
+-------------+--------------+-----+------------+----------------------+
| Field       | Type         | Key | Default    | Extra                |
+-------------+--------------+-----+------------+----------------------+
| id          | int(11)      | PRI | NULL       | auto_increment       |
| title    
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值