# 在项目中使用 TypeORM

TypeORM 官网介绍

TypeORM 是一个 ORM 框架,它可以运行在 NodeJS、Browser、Cordova、PhoneGap、Ionic、React Native、Expo 和 Electron 平台上,可以与 TypeScript 和 JavaScript (ES5,ES6,ES7,ES8) 一起使用。 它的目标是始终支持最新的 JavaScript 特性并提供额外的特性以帮助你开发任何使用数据库的(不管是只有几张表的小型应用还是拥有多数据库的大型企业应用)应用程序。

不同于现有的所有其他 JavaScript ORM 框架,TypeORM 支持 Active Record 和 Data Mapper 模式,这意味着你可以以最高效的方式编写高质量的、松耦合的、可扩展的、可维护的应用程序。

个人理解作用是

  1. 可以链接不同的数据库,MySQL、PostgreSQL、MongoDB...
    2. 可以在项目中写入实体然后映射到数据库中 (大白话的意思就是可以在项目中写数据表,然后自动映射到数据库中)
  2. TypeORM 中提供了很多 api 去 操控数据库。
    这里使用的是 MySQL 所以也需要下载 MySQL 的依赖包

# 安装依赖

yarn add @nestjs/typeorm typeorm mysql2

在 app.module.ts 中导入

//app.module.ts
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { TypeOrmModule } from '@nestjs/typeorm';// 引入 typeorm
import { UsersModule } from './users/users.module';
@Module({
  controllers: [AppController,],
  providers: [AppService],
  imports: [TypeOrmModule.forRoot({
    "type": "mysql",
    "host": "localhost",// 数据库地址
    "port": 3306,// 数据库端口
    "username": "root",
    "password": "9999999",
    "database": "blog",// 数据库名称
    "retryAttempts":10,// 连接数据库的尝试次数(默认:10)
    "autoLoadEntities": true,// 如果 true, 实体将被自动加载 (默认: false)
    "synchronize": true
  }),UsersModule],
})
export class AppModule {}

# 实体

官网介绍:

实体是一个映射到数据库表(或使用 MongoDB 时的集合)的类。 你可以通过定义一个新类来创建一个实体,并用 @Entity () 来标记:

个人理解:

实体是相当于数据库中的表,可以通过 typeorm 提供的 一些装饰器来创建每一列,每张表都需要一个 @Entity () 装饰器来标记

import { Entity, PrimaryGeneratedColumn, Column } from "typeorm";
@Entity()
export class Users {
    @PrimaryGeneratedColumn()
    id: number;
    @Column()
    firstName: string;
    @Column()
    lastName: string;
    @Column()
    isActive: boolean;
}

将会创建

+-------------+--------------+----------------------------+
|                          users                           |
+-------------+--------------+----------------------------+
| id          | int(11)      | PRIMARY KEY AUTO_INCREMENT |
| firstName   | varchar(255) |                            |
| lastName    | varchar(255) |                            |
| isActive    | boolean      |                            |
+-------------+--------------+----------------------------+

`

举例子 创建用户模块 并且写入用户实体,生成用户表

使用命令创建

  • nest g co
  • nest g s
  • nset g m

创建完文件夹后中,users 文件下 创建 users.entities 文件

//users.entities.ts
import { Column, CreateDateColumn, UpdateDateColumn, Entity, PrimaryGeneratedColumn } from "typeorm"
@Entity()
export class Users {
   
   // 使用 @PrimaryGeneratedColumn () 
    // @PrimaryGeneratedColumn ('uuid') 自动生成 uuid
    @PrimaryGeneratedColumn('uuid')
    id: string
    @Column({
        type: 'varchar',// 字段类型 
        comment: '用户名',// 备注
        nullable: false,// 是否可以为 null 默认是 false
        length: 128,// 长度
    })
    username: string// 字段名
    @Column({
        type: 'varchar',
        comment: '用户昵称',
        length: 128
    })
    user_nickname: string
    @Column({
        type: 'varchar',
        comment: '用户密码',
        length: 64
    })
    password: string
    @Column({
        type: 'varchar',
        comment: '用户手机号',
        length: 11
    })
    phone: number
    @Column({
        nullable: true,
        type: 'varchar',
        comment: '用户头像',
        length: 128,
        default:"xxx"
    })
    avatar: string
    // 自动为实体插入日期。无需设置此列,该值将自动设置。
    @CreateDateColumn()
    createTime: Date;
    // 在每次调用实体管理器或存储库的 save 时,自动更新实体日期。无需设置此列,该值将自动设置。
    @UpdateDateColumn()
    updateTime: Date;
}

注意:写完实体后 别忘记在 users.module.ts 文件中导入并使用 TypeOrmModule.forFeature ([]) 进行注册

<!--users.module.ts-->
import { Module } from '@nestjs/common';
// 导入 TypeOrmModule
import { TypeOrmModule } from '@nestjs/typeorm';
import { Users } from './users.entities';
import { UsersController } from './users.controller';
import { UsersService } from './users.service';
 
//TypeOrmModule.forFeature 注册实体 Users
// TypeOrmModule.forFeature([ArticleEntities])
@Module({ imports:[TypeOrmModule.forFeature([Users])],
controllers: [UsersController],providers:[UsersService]})
export class UsersModule {}

想了解更多实体中的装饰器,可以去 TypeORM 官网,点击链接跳转 https://typeorm.bootcss.com/entities

# 链接多个数据库

注意:
1、链接多个数据库时,不写 name 属性,name 默认是 defaul
2、需要注意每个数据库的 name 不能为空或者是重复

//app.module.ts
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { TypeOrmModule } from '@nestjs/typeorm';// 引入 typeorm
// 子模块加载
import { UsersModule } from './users/users.module';
const defaultOptions = {
  type: 'mysql',// 数据库类型
  port: 5432,// 端口
  username: 'user',// 登录名
  password: 'password'// 密码
  synchronize: true,
};
@Module({
  imports: [
    TypeOrmModule.forRoot({
      ...defaultOptions,
        database: 'blog',// 数据库名称
        name:"data1",
      host: 'user_db_host',// 数据库地址
    }),
    TypeOrmModule.forRoot({
      ...defaultOptions,
        database: 'blog1',// 数据库名称
      name: 'data2',//
      host: 'album_db_host',// 数据库地址
    }),
    UsersModule
  ],
  
  
})
export class AppModule {}

注意:
1、链接多个数据库时子模块中导入的实体 需要标明是哪个数据库

<!--users.module.ts-->
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { Users } from './users.entities';
import { UsersController } from './users.controller';
import { UsersService } from './users.service';
 
// 注册实体 Users
// TypeOrmModule.forFeature ([ArticleEntities],' 数据库 name')
@Module({ imports:[TypeOrmModule.forFeature([Users],'data1')], 
controllers: [UsersController],providers:[UsersService]})
export class UsersModule {}

操作数据库
利用 TypeORM 提供的一些 api 去操控数据库
如:
find()
findOne()
save()
remove()
...
例:

//users.service.ts
import { HttpCode, HttpStatus, Injectable, NotFoundException } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { User } from './entities/user.entities';
let status = {
    success: {
        code: HttpStatus.OK,
        message: "操作成功"
    }
};
@Injectable()
export class UsersService {
    constructor(
    // 用 @InjectRepository () 装饰器将 UsersRepository 注入到 UsersService 中
        @InjectRepository(User)
        private readonly UsersRepository: Repository<User>
    ) { }
    // 查询全部用户
    findAll() {
        return this.UsersRepository.find()
    }
    // 根据 id 查询用户
    async findOne(id: string) {
        const user = await this.UsersRepository.findOne({ where: { id } })
        if (!user) {
            throw new NotFoundException(`user #${id} is not found`)
        }
        return user
    }
    // 创建用户
    async create(CreateUserDto: CreateUserDto) {
        let { username } = CreateUserDto
        const name = await this.UsersRepository.findOne({ where: { username } })
        if (name) {
            return {
                code: HttpStatus.UNPROCESSABLE_ENTITY,
                message: "用戶名已存在"
            }
        }
        // 创建用户
        const user = this.UsersRepository.create(CreateUserDto)
        try {
            await this.UsersRepository.save(user)
        } catch (error) {
            return {
                code: HttpStatus.UNPROCESSABLE_ENTITY,
                message: error.driverError.sqlMessage
            }
        }
        return status.success
    }
    // 根据用户 id 删除用户
    async remove(id: string) {
        const user = await this.UsersRepository.findOne({ where: { id } })
        const res = await this.UsersRepository.remove(user)
        if (res) {
            return status.success
        }
    }
}
save(user)            创建:返回该数据的所有字段
insert(user)          快速插入一条数据,插入成功:返回插入实体,与save方法不同的是,它不执行级联、关系和其他操作。
remove(user)          删除:返回该数据的可见字段
softRemove(user);     拉黑:返回该数据的可见字段,该删除实体必须拥有@DeleteDateColumn()字段,被拉黑的用户还存在数据库中,但无法被find查找到,会在@DeleteDateColumn()字段中添加删除时间,可使用recover恢复
update(id, user)      更新:返回更新实体,不是该数据的字段
恢复
recover({ id })       恢复:返回id,将被softRemove删除(拉黑)的用户恢复,恢复成功后可以被find查找到
查找全部
find()
find({id:9})                   条件查找,写法一,找不到返回空对象
find({where:{id:10}})          条件查找,写法二,找不到返回空对象
findAndCount()                 返回数据和总的条数
查找一个
findOne(id);                       根据ID查找,找不到返回undefined
findOne({ where: { username } });  条件查找,找不到返回undefined
根据ID查找一个或多个
findByIds([1,2,3]);            查找n个,全部查找不到返回空数组,找到就返回找到的
其他
hasId(new UsersEntity())       检测实体是否有合成ID,返回布尔值
getId(new UsersEntity())       获取实体的合成ID,获取不到返回undefined
create({username: 'admin12345', password: '123456',})  创建一个实体,需要调用save保存
count({ status: 1 })           计数,返回数量,无返回0
increment({ id }, 'age', 2);   增加,给条件为id的数据的age字段增加2,成功返回改变实体
decrement({ id }, 'age', 2)    减少,给条件为id的数据的age字段增加2,成功返回改变实体
谨用
findOneOrFail(id)              找不到直接报500错误,无法使用过滤器拦截错误,不要使用
clear()                        清空该数据表,谨用!!!

我们形形色色,像无数条河里的水各自流淌,演绎出不一样的故事后,还是要以一样的姿态走上死亡这条路,一切伪装、恐惧、欣喜、慌张,都会有渐渐淡去的那一天。
————《我的郁金香小姐》

更新于 阅读次数

请我喝[茶]~( ̄▽ ̄)~*

温凯 微信支付

微信支付

温凯 支付宝

支付宝