typeorm-入门

news2024/11/18 5:57:52

简述

typeorm是一个数据库orm框架,在nestjs官网中有提到,可以充分发挥利用typescript的特性,当然也支持js其中涉及的概念包括

  • DataSource 数据源,Connection 连接数据库
  • Entity 实体,实体类映射数据库表
  • Relation 关系,定义实体类之间的关系,也就是数据库表之间的关系,一对一,多对一,多对多。
  • Entity Manager和Repository,Entity Manager可以管理创建连接时配置的所有实体,而Repository只能操作对应的实体,两个的api几乎的差不多的
  • QueryBuilder,用来创建更复杂的sql查询,灵活度比较高。

使用typeorm cli快速创建项目

全局安装typeorm
typeorm cli的相关命令,可以快速测试初始化项目,生成实体等等

npm install typeorm -g

初始化项目

typeorm init --name MyProject 

安装连接数据库驱动包,这里以msyql为2,安装msyql2

npm install mysql2

创建连接

import "reflect-metadata"
import { DataSource } from "typeorm"

export const AppDataSource = new DataSource({
  type: "mysql",
  host: "localhost",
  port: 3306,
  username: "root",
  password: "zhuang",
  database: "typeorm_test",// 连接的数据库
  synchronize: true,// 开发过程使用,可以同步修改表结构,生产切忌使用。
  logging: true,// 打印输出sql语句
  connectorPackage: "mysql2",// 驱动包
  entities: ["./**/entity/*.ts"],// 指定entity文件,也可以是实体数组,[User]
  migrations: [],
  subscribers: []
})

定义实体Entity

使用typeorm的装饰器定义实体
装饰器列表

快速成实体

typeorm entity:create -n User
typeorm entity:create src/entity/HelloWorld # 快速生成实体类

实体装饰器

  • @Entity(),@Entity({name:“指定表名”}) ,声明该类是实体类,对应表,表名默认是类名 Class 的小写下划线分割。
@Entity()
@Entity("user")
@Entity({
	name: "users",// 表名
    engine: "MyISAM", // 数据库引擎
    database: 'example_dev',// 数据库
    synchronize: false,// 是否同步更该表结构
    orderBy: {// 查询时的默认排序
        name: "ASC",
        id: "DESC"
    }
})

在这里插入图片描述

  • @ViewEntity(),视图实体,不会对应表
@ViewEntity({ 
    expression: `
        SELECT "post"."id" "id", "post"."name" AS "name", "category"."name" AS "categoryName"
        FROM "post" "post"
        LEFT JOIN "category" "category" ON "post"."categoryId" = "category"."id"
    `
})
export class PostCategory {}

列装饰器

  • @Column(),用来定义实体对应表列,默认对应的列名就是实体的属性名,可以配置,属性的数据类型没有显示指定的话,typeorm会根据ts的类型自动推断,在mysql中,string - varchar(255), boolean - tinyint, number - int,Date - datetime(6)
  • @PrimaryGeneratedColumn(), 相当于@Column({primary:true})具体的列装饰器都是固定了一些配置的装饰器.
  • @CreateDateColumn(),自动插入
  • @UpdateDateColumn(),自动更新
@Entity("users")
export class User {
    @Column({ primary: true }) // 配置主键, @PrimaryGeneratedColumn("uuid"),配置uuid主键
    id: number;

    @Column({ type: "varchar", length: 200, unique: true })// 配置数据库中具体类型,长度,唯一
    firstName: string;

    @Column({ nullable: true })// 配置是否为空
    lastName: string;

    @Column({ default: false })// 配置默认值,boolen默认类型被转换为 tinyint, false 对应 0,true 对应 1
    isActive: boolean;
    
	@CreateDateColumn() // 创建时自动插入
    createdDate: Date;
    
	@UpdateDateColumn() // 更新时自动更新
    updatedDate: Date;

	
}

关系装饰器

指定表之间的关系,默认配置会生成物理外键,可以通过配置RelationOptions{createForeignKeyConstraints:false},不生成外键约束。一般该配置位于装饰器的最后一个参数,如下配置:

/**
 * 描述表之间关系的配置
 */
export interface RelationOptions {
    /**
     * 配置不同表之间插入或更新时,相关的对象怎么配置,cascade:true 表示级联,如 user.roles, 当save的时候,把关联的roles实体也保存或者更新
     * If set to true then it means that related object can be allowed to be inserted or updated in the database.
     * You can separately restrict cascades to insertion or updation using following syntax:
     *
     * cascade: ["insert", "update", "remove", "soft-remove", "recover"] // include or exclude one of them
     */
    cascade?: boolean | ("insert" | "update" | "remove" | "soft-remove" | "recover")[];
    /**
     * Indicates if relation column value can be nullable or not.
     */
    nullable?: boolean;
    /**
     * 配置外键的onDelete
     * Database cascade action on delete.
     */
    onDelete?: OnDeleteType;
    /**
     * 配置外键的onUpdate
     * Database cascade action on update.
     */
    onUpdate?: OnUpdateType;
    /**
     * Indicate if foreign key constraints can be deferred.
     */
    deferrable?: DeferrableType;
    /**
     * Indicates whether foreign key constraints will be created for join columns.
     * Can be used only for many-to-one and owner one-to-one relations.
     * Defaults to true.
     * 创建外键,默认是true	
     */
    createForeignKeyConstraints?: boolean;
    /**
     * Set this relation to be lazy. Note: lazy relations are promises. When you call them they return promise
     * which resolve relation result then. If your property's type is Promise then this relation is set to lazy automatically.
     */
    lazy?: boolean;
    /**
     * Set this relation to be eager.
     * Eager relations are always loaded automatically when relation's owner entity is loaded using find* methods.
     * Only using QueryBuilder prevents loading eager relations.
     * Eager flag cannot be set from both sides of relation - you can eager load only one side of the relationship.
     */
    eager?: boolean;
    /**
     * Indicates if persistence is enabled for the relation.
     * By default its enabled, but if you want to avoid any changes in the relation to be reflected in the database you can disable it.
     * If its disabled you can only change a relation from inverse side of a relation or using relation query builder functionality.
     * This is useful for performance optimization since its disabling avoid multiple extra queries during entity save.
     */
    persistence?: boolean;
    /**
     * When a parent is saved (with cascading but) without a child row that still exists in database, this will control what shall happen to them.
     * delete will remove these rows from database.
     * nullify will remove the relation key.
     * disable will keep the relation intact. Removal of related item is only possible through its own repo.
     */
    orphanedRowAction?: "nullify" | "delete" | "soft-delete" | "disable";
}
  • OneToOne(),拥有该列的是从表,拥有关系的一方,即拥有xxxId的一方必须和@JoinColumn()配合使用。第一个参数是一个函数,返回关联的实体类,第二个参数如果有,是指定关系的反方,即关联字段的那方的实体类可以通过它的xxx属性来查询关系,第三个参数是配置关系的选项,包括 cascade级联,createForeignKeyConstraints创建外键,eager查询时总是把关系类也查出来。其他的关系装饰器也大抵如此。

cascade:true只能有一方配置,如果两边都配置cascade:true会报错,如果两边都配置,只要有一边不要配置cascade:[“remove”]就行。如果没有cascade:true关系,那么保存实体时,关联的实体必须先保存到数据库中,否则报错。
报错信息如下
在这里插入图片描述

@Entity()
export class User {
	// 指定关联实体,假如Profile实体通过@OnetoOne() 声明 user:User 字段,那么查询profile时也可以查询到user类
    @OneToOne(type => Profile, profile => profile.user,{
    	createForeignKeyConstraints:false// 不创建外键
	})
    @JoinColumn() // 表示user表有profileId字段关联 profile 表,
    profile: Profile;
}
  • ManyToOne(),拥有该列的表是从表,默认生成关联id,多对一的情况下,可以省略 @JointColumn(), 除非想指定 关联id 和关联列
  • OneToMany(),反向关系,用在一的一方
@Entity()
export class Photo {
  @PrimaryGeneratedColumn()
  id: number;

  @Column()
  url: string;
  // 第二个参数指定另一面关系的关联属性,这里可以省略 @JoinColumn(),默认生成字段 userId 
  @ManyToOne(() => User, user => user.photos) 
  user: User;
}

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

  @Column()
  name: string;

  @OneToMany(() => Photo, photo => photo.user) 
  photos: Photo[];
}
  • ManyToMany()
    双方都必须使用,而且必须有一方使用@JoinTable()
@Entity()
export class Post {
    @ManyToOne(type => Category)
    @JoinColumn({
        name: "cat_id",// 指定列名
        referencedColumnName: "name" // 引用的Category的列名
    })
    category: Category;
}
  • JoinColumn()
    指定关系列字段,用于一对一,多对一和多对多,可以设置 cascade,createForeignKeyConstraints,以及另一面的关系属性。
  • JoinTable()
    用于多对多添加中间表,并指定拥有关系的列,只需要一方添加即可。一般要配合@ManyToMany()使用,还可以配置关联表名称和指定关联的列名和关联表的列名
  • RelationId()
    可以获取关联的实体的id,包括多对一和多对多,此 id 仅用于展示,对其修改并不会增删改关系
@Entity()
export class Post {
    @ManyToOne(type => Category)
    category: Category;

    @RelationId((post: Post) => post.category) // 需要指定目标关系
    categoryId: number;
}

@Entity()
export class Post {
    @ManyToMany(type => Category)
    categories: Category[];

    @RelationId((post: Post) => post.categories)
    categoryIds: number[];
}

增删改查api

typeorm增删改查有三种途径:

  1. 通过 Entity Manager 的api,
  2. 通过 Repository 的api, 其中还包括了 TreeRepository(树结构的仓库) 和 MongoRepsotiry
  3. 通过 createQueryBuilder 的api构建sql

Entity Manager 和 Repository 的api基本相同,区别是 Manager 的api要指定实体类, 而 Repository 一般是通过 manager 指定 实体类获取到, 所以 Respository 可以少传一个类, 而 QueryBuilder 可以通过 数据源 DataSource.createQueryBuilder ,或者 实体管理器 Entity Manager 或者 Repository 来获取.

Entity Manager 和 Repository

这两者的api几乎相同,可以通过 manager.find(User,{where:{id:1}}) 等价与 manager.getRepositry(User).find({where:{id:1}})

简单示例:

import { DataSource } from "typeorm"
import { User } from "./entity/User"

const myDataSource = new DataSource(/*...*/)
//  这里 manager 指定了 User 类
const user = await myDataSource.manager.findOneBy(User, {
    id: 1,
})
user.name = "Umed"
await myDataSource.manager.save(user)

import { User } from "./entity/User"

// 这里通过 getRepository(User)  获取仓库
const userRepository = dataSource.getRepository(User)
const user = await userRepository.findOneBy({
    id: 1,
})
user.name = "Umed"
await userRepository.save(user)

新增
save,保存给定的实体或实体数组,如果该实体已存在,那么就是更新,所有这个方法会先使用 select 语句后看是否存在决定是 insert 还是update

await manager.save(user)
await manager.save([user1,user2,user3])

insert ,插入实体或实体数组

await manager.insert(User,{username:"xxx"})
await manager.insert(User,[{username:"xxx"},{username:"yyy"}])

删除
修改
查询

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

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

相关文章

30个炫酷光效视频转场PR模板剪辑素材下载

视频转场Premiere模板,包含30个炫酷光效视频转场过渡效果PR项目模板下载。 适用软件:Premiere Pro 2023 | 分辨率:3840x2160 (4K) | 无需插件 | 文件大小:56.33MB 来自PR转场,下载地址:https://prmuban.com…

Windows下Node.js安装保姆级教程

一、Node.js 下载 访问Node.js官网,点击下载Node.js 下载完成后即可在下载文件中查看安装包 二、安装 一)点击安装包开始安装,进入Weclcome界面点击Next 二)勾选同意协议,点击Next 三)根据需要选择安装路…

Neo4j安装 Linux:CentOS、openEuler 适配langchain应用RAG+知识图谱开发 适配昇腾910B

目录 Neo4j下载上传至服务器后进行解压运行安装JAVA再次运行在windows端打开网页导入数据 Neo4j下载 进入Neo4j官网下载页面 向下滑动找到 Graph Database Self-Managed 选择 社区版(COMMUNITY) 选择 Linux / Mac Executable Neo4j 5.17.0 (tar) 单机下…

Linux第72步_使用“新字符设备的一般模板”编写LED驱动

使用“新字符设备的一般模板”编写LED驱动,使用寄存器直接开关灯。 1、创建LED目录 输入“cd /home/zgq/linux/Linux_Drivers/回车” 切换到“/home/zgq/linux/Linux_Drivers/” 输入“ls回车”,查看“/home/zgq/linux/Linux_Drivers/” 输入“mkdi…

egg如何写单元测试

优秀的代码需要有单元测试进行质量保证,每个测试用例都给应用的稳定性提供了一层保障。 测试目录结构 我们约定 test 目录为存放所有测试脚本的目录,测试所使用到的 fixtures 和相关辅助脚本都应该放在此目录下。 测试文件的目录和我们需要测试的文件目…

unicloud where 使用

where介绍 在uniCloud中,WHERE是一个用于指定查询条件的关键字。它允许用户根据特定的条件来筛选和查询云数据库中的数据。WHERE语句的基本语法格式是WHERE condition,其中condition表示查询条件,可以是一个或多个逻辑表达式组成的条件。 在…

深入了解304缓存原理:提升网站性能与加载速度

🤍 前端开发工程师、技术日更博主、已过CET6 🍨 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 🕠 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 🍚 蓝桥云课签约作者、上架课程《Vue.js 和 E…

探索HTTP协议:网络通信的基石

🤍 前端开发工程师、技术日更博主、已过CET6 🍨 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 🕠 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 🍚 蓝桥云课签约作者、上架课程《Vue.js 和 E…

消息队列-kafka-消息发送流程(源码跟踪) 与消息可靠性

官方网址 源码:https://kafka.apache.org/downloads 快速开始:https://kafka.apache.org/documentation/#gettingStarted springcloud整合 发送消息流程 主线程:主线程只负责组织消息,如果是同步发送会阻塞,如果是异…

web基础04-flex布局

1.概述 Flexbox​ 是 ​flexible box​ 的简称(注:意思是“​灵活的盒子容器​”),是 CSS3 引入的新的布局模式。 它决定了元素如何在页面上排列,使它们能在不同的屏幕尺寸和设备下可预测地展现出来。 它之所以被称…

C++错误总结(1)

1.定义函数类型时,如果没有返回值,用void void swap(int &x, int &y){ int tem x; x y; y tem; } 2.输入时,不加换行符 cin >> a >> b >> c >> endl ;(红色标记的是错误的部分) 3.【逆序出入…

【LeetCode】升级打怪之路 Day 16:二叉树题型 —— 二叉树的构造

今日题目: 654. 最大二叉树105. 从前序与中序遍历序列构造二叉树106. 从中序与后序遍历序列构造二叉树889. 根据前序和后序遍历构造二叉树 目录 LC 654. 最大二叉树 【easy】 Problem:根据遍历序列来还原二叉树 【classic】 ⭐⭐⭐⭐⭐LC 105. 从前序与中…

华为设备小型园区网方案(有线+无线+防火墙)

(一)配置有线部分 1.配置LSW2 (1)创建相关vlan [LSW2]vlan batch 10 3000 (2)配置连接LSW1的Eth-Trunk1,透传VLAN 10 3000 [LSW2]int Eth-Trunk 1 [LSW2-Eth-Trunk1]port link-type trunk [LSW2…

微信小程序(五十四)腾讯位置服务示范(2024/3/8更新)

教程如下: 上一篇 1.先在官网注册一下账号(该绑定的都绑定一下) 腾讯位置服务官网 2.进入控制台 3.创建应用 3. 额度分配 4.下载微信小程序SDK 微信小程序SDK下载渠道 5.解压将俩js文件放在项目合适的地方 6.加入安全域名or设置不验证合…

自动化工程师涨薪难,原因出在这里

大家好,今天说说真实的工控行业,摒弃虚无的鸡汤,聊点实在的。 举个例子,某工做销售,卖电控器件,眼见PLC收入可观,开始感到压力。于是,他下定决心学PLC,报了培训班。毕业后…

Flink并行度

1、Task flink中每个算子就是一个Task,比如flatMap、map、sum是一个Task。 2、SubTask 算子有几个并行度SubTask的数量就是几,比如 3、算子并行度 算子并行度指的是每个算子的并行度,可用env.setParallelism(1);设置所有算子的并行度&am…

防御保护--IPSEC VPPN实验

实验拓扑图 实验背景:FW1和FW2是双机热备的状态。 实验要求:在FW5和FW3之间建立一条IPSEC通道,保证10.0.2.0/24网段可以正常访问到192.168.1.0/24 IPSEC VPPN实验配置(由于是双机热备状态,所以FW1和FW2只需要配置FW1…

【树莓派+python】实现三色呼吸灯+按钮切换

文章目录 Traffic-lights电路连接在这里插入图片描述代码实现算法设计流程图python环境配置三色呼吸灯实现三色呼吸灯按钮控制 Traffic-lights 电路连接 【元件实物图】 图1为Button,按钮的状态控制SIG引脚的电平值。图2为RGB灯,有三种颜色&#xff1a…

项目解决方案:多地5G蓄能电站的视频监控联网系统设计方案

目 录 一、前言 二、系统架构设计 1、系统架构设计说明 2、系统拓扑图 三、关键技术 1. 5G支持技术 2. 视频图像处理技术 3. 数据融合与分析技术 四、功能特点 1. 高效可靠 2. 实时监测 3. 远程控制 4. 故障预测 五、应用前景 一、前言 随着能源…