【NestJs】使用MySQL创建多个实体

news2025/1/18 9:47:02

如果小伙伴还不会使用nestjs连接数据库的话 可以看我的上一篇文章 NestJs使用连接mysql企业级开发规范

关系

关系是指两个或多个表之间的联系。关系基于每个表中的常规字段,通常包含主键和外键。关系有三种:

名称说明
一对一主表中的每一行在外部表中有且仅有一个对应行。使用@OneToOne()装饰器来定义这种类型的关系
一对多/多对一主表中的每一行在外部表中有一个或多的对应行。使用@OneToMany()和@ManyToOne()装饰器来定义这种类型的关系
多对多主表中的每一行在外部表中有多个对应行,外部表中的每个记录在主表中也有多个行。使用@ManyToMany()装饰器来定义这种类型的关系

user.entity.ts

import {
  Column,
  Entity,
  PrimaryGeneratedColumn,
} from 'typeorm';


@Entity() // 最终实现实体类
export class User {
  @PrimaryGeneratedColumn()
  id: number;

  @Column()
  username: string;

  @Column()
  password: string;
}

可以使用navicat 查看创建的user表
在这里插入图片描述

再来创建一个profile.entity.ts

import {
  Column,
  Entity,
  JoinColumn,
  OneToOne,
  PrimaryGeneratedColumn,
} from 'typeorm';

@Entity()
export class Profile {
  @PrimaryGeneratedColumn()
  id: number;

  @Column()
  gender: number;

  @Column()
  photo: string;

  @Column()
  address: string;
}

再来创建一个roles.entity.ts

import { Column, Entity, ManyToMany, PrimaryGeneratedColumn } from 'typeorm';

@Entity()
export class Roles {
  @PrimaryGeneratedColumn()
  id: number;

  @Column()
  name: string;
}

再来创建一个logs.entity.ts

import {
  Column,
  Entity,
  JoinColumn,
  ManyToOne,
  PrimaryGeneratedColumn,
} from 'typeorm';

@Entity()
export class Logs {
  @PrimaryGeneratedColumn()
  id: number;

  @Column()
  path: string;

  @Column()
  methods: string;

  @Column()
  data: string;

  @Column()
  result: number;
}

创建完之后别忘记把这个四个实体 添加到app.module.ts

import { Module } from '@nestjs/common';
import { UserModule } from './user/user.module';
import { ConfigModule, ConfigService } from '@nestjs/config';
import * as dotenv from 'dotenv';
import * as Joi from 'joi';
import { TypeOrmModule, TypeOrmModuleOptions } from '@nestjs/typeorm';
import { ConfigEnum } from './enum/config.enum';

import { User } from './user/user.entity';
import { Profile } from './user/profile.entity';
import { Logs } from './logs/logs.entity';
import { Roles } from './roles/roles.entity';

const envFilePath = `.env.${process.env.NODE_ENV || `development`}`;

@Module({
  imports: [
    ConfigModule.forRoot({
      isGlobal: true,
      envFilePath,
      load: [() => dotenv.config({ path: '.env' })],
      validationSchema: Joi.object({
        NODE_ENV: Joi.string()
          .valid('development', 'production')
          .default('development'),
        DB_PORT: Joi.number().default(3306),
        DB_HOST: Joi.string().ip(),
        DB_TYPE: Joi.string().valid('mysql', 'postgres'),
        DB_DATABASE: Joi.string().required(),
        DB_USERNAME: Joi.string().required(),
        DB_PASSWORD: Joi.string().required(),
        DB_SYNC: Joi.boolean().default(false),
      }),
    }),
    TypeOrmModule.forRootAsync({
      imports: [ConfigModule],
      inject: [ConfigService],
      useFactory: (configService: ConfigService) =>
        ({
          type: configService.get(ConfigEnum.DB_TYPE),
          host: configService.get(ConfigEnum.DB_HOST),
          port: configService.get(ConfigEnum.DB_PORT),
          username: configService.get(ConfigEnum.DB_USERNAME),
          password: configService.get(ConfigEnum.DB_PASSWORD),
          database: configService.get(ConfigEnum.DB_DATABASE),
          entities: [User, Profile, Logs, Roles],
          // 同步本地的schema与数据库 -> 初始化的时候去使用
          synchronize: configService.get(ConfigEnum.DB_SYNC),
          logging: process.env.NODE_ENV === 'development',
          // logging: ['error'],
        } as TypeOrmModuleOptions),
    }),
    // TypeOrmModule.forRoot({
    //   type: 'mysql',
    //   host: 'localhost',
    //   port: 3306,
    //   username: 'root',
    //   password: 'example',
    //   database: 'testdb',
    //   entities: [],
    //   // 同步本地的schema与数据库 -> 初始化的时候去使用
    //   synchronize: true,
    //   logging: ['error'],
    // }),
    UserModule,
  ],
  controllers: [],
  providers: [],
})
export class AppModule {}

这样我们就创建好了表
在这里插入图片描述
接下来我们来创建表和表之间的关系

在这里插入图片描述
通过这个er图我们很容易看出表与表之间的关系。
接下来我们现在profile.entity.ts中创创建和user表的关系

一对一

一对一是一种 A 只包含一个 B 实例,而 B 只包含一个 A 实例的关系。 我们以User和Profile实体为例。

用户只能拥有一个配置文件,并且一个配置文件仅由一个用户拥有。

import {
  Column,
  Entity,
  JoinColumn,
  OneToOne,
  PrimaryGeneratedColumn,
} from 'typeorm';
import { User } from './user.entity';

@Entity()
export class Profile {
  @PrimaryGeneratedColumn()
  id: number;

  @Column()
  gender: number;

  @Column()
  photo: string;

  @Column()
  address: string;

  @OneToOne(() => User)
  @JoinColumn()  // 会默认使用小驼峰 创建一个字段进行连接
  //  @JoinColumn({name:'userId'}) 
  user: User;
}

这里我们将@OneToOne添加到user并将目标关系类型指定为User。 我们还添加了@JoinColumn,这是必选项并且只能在关系的一侧设置。 你设置@JoinColumn的哪一方,哪一方的表将包含一个"relation id"和目标实体表的外键。
同样,@JoinColumn必须仅设置在关系的一侧且必须在数据库表中具有外键的一侧。

 @OneToOne(() => User)
 // 使用函数 我们在需要的地方再次调用
 // 我们并不需要关系User类里面的内容

在这里插入图片描述

多对一/一对多的关系

多对一/一对多是指 A 包含多个 B 实例的关系,但 B 只包含一个 A 实例。 让我们以User 和 Logs实体为例。 User 可以拥有多张 Logs,但每张 Log 仅由一位 user 拥有。

import {
  Column,
  Entity,
  PrimaryGeneratedColumn,
  OneToMany,
  ManyToMany,
  JoinTable,
  OneToOne,
} from 'typeorm';
import { Logs } from '../logs/logs.entity';

@Entity()
export class User {
  @PrimaryGeneratedColumn()
  id: number;

  @Column()
  username: string;

  @Column()
  password: string;

  // typescript -> 数据库 关联关系 Mapping
  @OneToMany(() => Logs, (logs) => logs.user)
  logs: Logs[];
}

logs.entity.ts

import {
  Column,
  Entity,
  JoinColumn,
  ManyToOne,
  PrimaryGeneratedColumn,
} from 'typeorm';
import { User } from '../user/user.entity';

@Entity()
export class Logs {
  @PrimaryGeneratedColumn()
  id: number;

  @Column()
  path: string;

  @Column()
  methods: string;

  @Column()
  data: string;

  @Column()
  result: number;
  // typescript 数据库 关联关系
  @ManyToOne(() => User, (user) => user.logs)
  //   user.logs 建立 OneToMany 的关系
  @JoinColumn()
  user: User;
}

这里我们将@OneToMany添加到logs属性中,并将目标关系类型指定为Logs。 你可以在@ManyToOne / @OneToMany关系中省略@JoinColumn,除非你需要自定义关联列在数据库中的名称。 @ManyToOne可以单独使用,但@OneToMany必须搭配@ManyToOne使用。 如果你想使用@OneToMany,则需要@ManyToOne。 在你设置@ManyToOne的地方,相关实体将有"关联 id"和外键。

在这里插入图片描述

多对多的关系

多对多是一种 A 包含多个 B 实例,而 B 包含多个 A 实例的关系。 我们以User和 Roels实体为例。

user.entity.ts

import {
  Column,
  Entity,
  PrimaryGeneratedColumn,
  OneToMany,
  ManyToMany,
  JoinTable,
  OneToOne,
} from 'typeorm';
import { Logs } from '../logs/logs.entity';
import { Roles } from '../roles/roles.entity';
import { Profile } from './profile.entity';

@Entity()
export class User {
  @PrimaryGeneratedColumn()
  id: number;

  @Column()
  username: string;

  @Column()
  password: string;

  // typescript -> 数据库 关联关系 Mapping
  @OneToMany(() => Logs, (logs) => logs.user)
  logs: Logs[];

  @ManyToMany(() => Roles, (roles) => roles.users)
  // 建立中间表
  @JoinTable({ name: 'users_roles' })
  roles: Roles[];

  @OneToOne(() => Profile, (profile) => profile.user)
  profile: Profile;
}

roles.entity.ts

import { Column, Entity, ManyToMany, PrimaryGeneratedColumn } from 'typeorm';
import { User } from '../user/user.entity';

@Entity()
export class Roles {
  @PrimaryGeneratedColumn()
  id: number;

  @Column()
  name: string;

  @ManyToMany(() => User, (user) => user.roles)
  users: User[];
}

在这里插入图片描述
到此为止 我们介绍了 一对一,一对多,多对多的关系,当然也都是从0到1 创建表的过程。恭喜,你成功进步了一大截。那么企业中都是0到1的场景吗?当然不是,那要是在原有的库上增加数据我们该怎么办呢?
接下来我们要介绍 旧项目中已有数据库我们怎么使用TypeORM
那么我们需要了解一下一个库:typeorm-model-generator
在这里插入图片描述
局部安装

pnpm i -D typeorm-model-generator

然后 使用 package.json 新增一个命令

"generate:models": "typeorm-model-generator -h 127.0.0.1 -p 3306 -d testdb -u root -x 123456 -e mysql -o ./src/entities"

开始执行
在这里插入图片描述
项目中会生成一个 entities文件夹

在这里插入图片描述
注意
如果是旧项目 还是放在 entities 里面,后面新项目还是单独放

启动项目,启动成功,之前库也都存在了。
下面一篇文章介绍 创建实体功能NestJs使用MySQL创建多个实体

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/428126.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

从零到一发布 NPM 包

如果你负责前端的基础能力建设,发布各种功能/插件包犹如家常便饭,所以熟悉对 npm 包的发布与管理是非常有必要的,故此有了本篇总结文章。本篇文章一方面总结,一方面向社区贡献开箱即用的 npm 开发、编译、发布、调试模板&#xff…

【展会邀请】百华与您相约第104届中国劳动保护用品交易会!

重磅消息!一场行业极具规模的劳保展 第104届中国劳动保护用品交易会 暨2023中国国际职业安全及健康产业博览会 将于2023.4.13-15在上海新国际博览中心E1-E7馆隆重举办! 山东百华鞋业有限公司受邀参展,正在火热筹备中。 百华展位号 2023…

算法:将一个数组旋转k步

题目 输入一个数组如 [1,2,3,4,5,6,7],输出旋转 k 步后的数组。 旋转 1 步:就是把尾部的 7 放在数组头部前面,也就是 [7,1,2,3,4,5,6]旋转 2 步:就是把尾部的 6 放在数组头部前面,也就是 [6,7,1,2,3,4,5]… 思路 思…

PasteSpider的下载和安装

你是否在纠结于k8s的庞大和复杂,是否在被混论的发布流程搞得焦头烂额。PasteSpider适合你!足够小的内存资源消耗(300MB甚至更低!),不需要专业的运维知识,图文操作,支持一键发布,支持自动路由配置…

泛型基本说明

使用传统方法的问题分析 不能对加入到集合ArrayList中的数据类型进行约束(不安全)遍历的时候,需要进行类型转换,如果集合中的数据量较大,对效率有影响。泛型的好处 编译时,检查添加元素的类型,提…

springbean 的 setter/构造注入

文章目录前言一、另外两种注入的怎么用?二、使用setter和构造注入的步骤1. 搞一个配置类,用户获取spring容器中的bean2. 由于有静态方法,所以直接调用三、使用final 的构造注入方式(推荐)总结前言 我们知道,一般java中的依赖注入有三种: 1 属性注入 2 settter注入 …

Golang每日一练(leetDay0039) 二叉树专题(8)

目录 115. 不同的子序列 Distinct Subsequences 🌟🌟🌟 116. 填充每个节点的下一个右侧节点指针 Populating-next-right-pointers-in-each-node 🌟🌟 117. 填充每个节点的下一个右侧节点指针 II Populating-next-ri…

模拟信号放大转换器 非隔离 线性对应输入输出 大功率负载

概述: 导轨安装DIN11 NIPO 系列模拟信号放大器是一种将输入信号放大、转换成按比例输出的直流信号放大器。产品广泛应用在电力、远程监控、仪器仪表、医疗设备、工业自控等需要直流信号测控的行业。此系列产品内部采用稳压电路,通过等比例控制线性放大输…

Threshold ECDSA——web3.0开发中的门限签名

多重签名 1.联名账户,任何一个密钥都能打开账户。 2.储蓄账户,需要所有密钥才能打开账户。 3.级联账户,可以使用部分密钥做部分功能,需要所有密钥才能执行全部功能。 4.在加密货币中,多重签名通过创建一个多重签名…

超详细从入门到精通,pytest自动化测试框架实战-fixture多样玩法(九)

目录:导读前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结(尾部小惊喜)前言 在编写测试用例&…

uniapp开发小程序:使用webview 跳转外部链接

一、使用uniapp开发小程序时,要跳转外部链接,实现的效果如下: 二、实现的步骤: ①先在自己uniapp项目pages.json中建一个页面webview.vue {"path" : "pages/webview/webview","style" : …

(详细)带你运行ShanghaiTech数据集预训练模型——人群计数算法

写在前面 ShanghaiTech数据集是现有的人群计数领域比较常用的训练测试数据集,该博客将详细讲述如何跑通ShanghaiTech官方提供的预训练版本。 由于全部跑完ShanghaiTech数据集需要一定的时间,今天只以其中的ped2数据集(体量最小)…

linux_回收子进程(何为孤儿进程、僵尸进程、wait函数、waitpid函数)

接上一篇:linux_exec函数族-execl函数-execlp函数-execle函数-execv函数-execvp函数-execve函数 今天来向大家分享几个有趣的知识点,一个是孤儿进程,一个是僵尸进程,hhh,是不是很有趣,另外再来看看怎么去回…

Kubernetes集群调度增强之超容量扩容

作者:京东科技 徐宪章 1 什么是超容量扩容 超容量扩容功能,是指预先调度一定数量的工作节点,当业务高峰期或者集群整体负载较高时,可以使应用不必等待集群工作节点扩容,从而迅速完成应用横向扩容。通常情况下HPA、Cl…

链表与邻接表|栈与队列|kmp

目录 单链表(邻接表) 双链表 数组模拟栈、队列 单调栈 单调队列(滑动窗口) KMP 一、KMP算法基本概念与核心思想 二、next数组的含义 三、匹配的思路 四、求next数组 单链表(邻接表) #include &…

Linux操作基础(系统安全及应用)

文章目录一 、账号安全基本措施1.1 系统账号清理1.2 密码安全控制1.21 设置密码有效期1.3 命令历史限制1.31 修改history命令条数1.32 清空history的方式1.33 设置终端自动注销二 、使用su命令切换用户2.1 限制使用su命令切换用户2.2 sudo命令—提升执行权限三 、系统引导和登录…

OpenCV:介绍 SURF(加速稳健特征)以及其使用

我们将了解 SURF 的基础知识 我们将了解 OpenCV 中的 SURF 功能 理论 在上一章中,我们学习了 SIFT 用于关键点检测和描述的方法。但它相对较慢,人们需要更快速的版本。2006年,Bay, H., Tuytelaars, T. 和 Van Gool, L 发表了另一篇论文 "SURF: 加速稳健特征",介…

机器学习:多项式拟合分析中国温度变化与温室气体排放量的时序数据

文章目录1、前言2、定义及公式3、案例代码1、数据解析2、绘制散点图3、多项式回归、拟合4、注意事项1、前言 ​ 当分析数据时,如果我们找的不是直线或者超平面,而是一条曲线,那么就可以用多项式回归来分析和预测。 2、定义及公式 ​ 多项式…

《花雕学AI》哪种技能5年10年后还会被市场需要? 该如何提高这些能力?

随着AI人工智能、ChatGPT等新的技术革新的发展,未来职业场景确实会发生变化,一些传统的职业可能会被取代,而一些新的职业可能会出现。根据世界经济论坛所发布的《未来就业报告》,一半的劳动力需要在2025年之前完成技能重塑。那么&…

Harmony OS 开发指南——DevEco Device Tool 安装配置

本文介绍如何在Windows主机上安装DevEco Device Tool工具。 坑点总结: 国内部分网络环境下,安装npm包可能会很慢或者超时,推荐使用国内npm源(如淘宝源、华为源等);serialport这个npm包安装的过程中需要编…