概述
- TypeORM是一个对象关系映射框架,它可以运行在 NodeJS、Browser、Cordova、PhoneGap、Ionic、React Native、Expo 和 Electron 平台上,
- 可以与 TypeScript 和 JavaScript (ES5,ES6,ES7,ES8)一起使用。
- 它的目标是始终支持最新的 JavaScript 特性并提供额外的特性以帮助你开发任何使用数据库的(不管是只有几张表的小型应用还是拥有多数据库的大型企业应用)应用程序。
- 还兼容各种主流数据库
官网
安装
npm install typeorm -g
tips: 如果出现安装失败,那么就是没有权限的问题。mac就在代码前输入sudo提升权限,windows就使用右键管理员身份运行再复制以上的代码。
生成项目
typeorm init --name MyProject --database mysql
- -name 跟着的是创建项目的项目名
- database 跟着的是要使用的数据库:mysql oracle SQL Server等
配置文件
{
"type": "mysql", //数据库类型
"host": "localhost",//数据库地址
"port": 3306, //端口号
"username": "test", //用户名
"password": "test", //密码
"database": "test", //使用哪一个数据库
"synchronize": true,//是否同步,true就是将src/entity里面定义的数据模块同步到数据库生成数据表
"logging": false, //是否打印日志,执行sql语句时候输出原生sql,也可以配置成一个数组["query", "error", "schema"]指定sql的执行类型
"entities": [
"src/entity/**/*.ts" //实体类的路径
],
"migrations": [
"src/migration/**/*.ts" //数据库迁移文件生成路径
],
"subscribers": [
"src/subscriber/**/*.ts"
],
"cli": {
"entitiesDir": "src/entity",
"migrationsDir": "src/migration",
"subscribersDir": "src/subscriber"
}
}
实体类
以自动生成的User.ts为例
import {Entity, PrimaryGeneratedColumn, Column} from "typeorm";
@Entity()
export class User {
@PrimaryGeneratedColumn()
id: number;
@Column({
type: 'varchar',//字段类型
nullable: false,//是否为空
length: 50,//长度
unique: true,//是否唯一
name: 'firstName', // 映射到表的字段名,如果是一样的可以不指定
comment: '字'
})
firstName: string;
@Column()
lastName: string;
@Column()
age: number;
- Entity() 就相当于映射到数据库中的表,class 的名字就对应表的名字
- PrimaryGeneratedColumn() 相对应表的主键,而且是自动递增的。
- PrimaryColumn() 这个就是主键不自动递增
- Column() 表示表中的列
- type配置字段类型,在mysql中字符类型可能是char、varchar、text,数字类型可能是int、tinyint,小数类型可能是float、double、decimal(10,2)等。
name: 真正映射到mysql数据库中字段名字,如果不指定会默认以对象的字段为名字(建议都指定)
length: 长度,比如在mysql中字段为varchar的时候指定字段长度
nullable: 在mysql中字段是否可以为NULL值,默认为false
select: 改字段是否可以被查询出来(针对使用typeORM的查寻操作,不针对你使用原生SQL语句操作),默认为true表示可以被查询出来
default: 默认值,比如插入数据的时候,没传递该字段的值,就默认一个值
unique: 是否唯一约束
comment: 备注该字段是做什么的(建议都写上,方便阅读)
enum: 枚举类型
array: 该列是否以数组 - 更多的注解
增删改查
- 查询
createConnection().then(async connection => {
console.log("Inserting a new user into the database...");
const user = new User();
user.firstName = "Timber";
user.lastName = "Saw";
user.age = 24;
const users = await connection.manager.find(User);
console.log("Loaded users: ", users);
}).catch(error => console.log(error));
除了find()之外还有一下几种方法
- 修改
createConnection().then(async connection => {
onst userRepository = connection.getRepository(User);
// 根据句柄去查询实体findOne传递数字会默认根据id查询
const user2 = await userRepository.findOne(1);
console.log(user2);
user2.firstName = "wdb";
await userRepository.save(user2);
}).catch(error => console.log(error));
结果:
- 删除
createConnection().then(async connection => {
onst userRepository = connection.getRepository(User);
const user2 = await userRepository.findOne(4);
await userRepository.remove(user2);
}).catch(error => console.log(error));
结果:
- 添加
第一种方式:通过save将对象添加进数据库
createConnection().then(async connection => {
const user = new User();
user.firstName = "Timber";
user.lastName = "Saw";
user.age = 24;
await connection.manager.save(user);
}).catch(error => console.log(error));
第二种方式:使用Repository句柄将对象添加进数据库
createConnection().then(async connection => {
const user = new User();
user.firstName = "Timber";
user.lastName = "Saw";
user.age = 28;
const userRepository = connection.getRepository(User);
userRepository.insert(user);
}).catch(error => console.log(error));
结果:
一对一
- 首先我们先创建UserExtend表,它是user表的详情表
import {
Entity,
PrimaryGeneratedColumn,
Column,
OneToOne,
JoinColumn,
} from "typeorm";
import { User } from "./User";
@Entity({ name: "user_extend" })
export class UserExtend {
@PrimaryGeneratedColumn()
id: number;
@Column({
type: "varchar",
length: 11,
nullable: true,
name: "mobile",
comment: "手机号码",
})
mobile: string;
@Column()
address: string;
// 使用@OneToOne装饰允许我们在两个实体之间创建一对一的关系
@OneToOne((type) => User, (user) => user.userDetail)
// @JoinColumn装饰器,表明实体键的对应关系
@JoinColumn()
user: User;
}
- 然后在user表中添加新的字段
import {Entity, PrimaryGeneratedColumn, Column,OneToOne,
JoinColumn} from "typeorm";
import { UserExtend } from "./UserExtend";
@Entity()
export class User {
@PrimaryGeneratedColumn()
id: number;
@Column()
firstName: string;
@Column()
lastName: string;
@Column()
age: number;
@OneToOne((type) => UserExtend, (userExtend) => userExtend.user)
@JoinColumn()
userDetail: UserExtend;
}
- 在index.ts中关联两个表的字段
import "reflect-metadata";
import {createConnection} from "typeorm";
import {User} from "./entity/User";
import {UserExtend} from "./entity/UserExtend";
createConnection().then(async connection => {
const user = new User();
user.firstName = "dwadawd";
user.lastName = "Sadasw";
user.age = 28;
const userExtend = new UserExtend();
userExtend.mobile = '13959058402';
userExtend.address = '福建省xxxxxxx';
//给两个数据模型关联起来
userExtend.user = user;
const userRepository = connection.getRepository(User);
//先插入user获取user的id
await userRepository.save(user);
const userExtendRepository = connection.getRepository(UserExtend);
await userExtendRepository.save(userExtend);
console.log('插入数据成功');
}).catch(error => console.log(error));
结果:
- 查询
查询用户详情表的user有字段的数据
createConnection().then(async connection => {
const userExtendRepository = connection.getRepository(UserExtend);
const result = await userExtendRepository.find({ relations: ["user"] });
console.log(result);
}).catch(error => console.log(error));
查询用户表的userDetail有字段的数据
createConnection().then(async connection => {
const userRepository = connection.getRepository(User);
// await userRepository.save(user);
const res = await userRepository.find({relations:["userDetail"]});
console.log(res);
}).catch(error => console.log(error));
- 一对多
我们先添加一个Article表,在表中关联userid
import {
Entity,
PrimaryGeneratedColumn,
Column,
CreateDateColumn,
UpdateDateColumn,
ManyToOne,
} from "typeorm";
import {User} from "./User"
@Entity()
export class Article {
@PrimaryGeneratedColumn({
type:"int",
name:"id",
comment:"id"
})
id:number;
@Column({
type:"varchar",
nullable:false,
length:255,
name:"title",
comment:"标题"
})
title:string;
@Column({
type:"varchar",
nullable:false,
length:255,
name:"summary",
comment:"摘要"
})
summary:string;
@Column({
type:"varchar",
nullable:false,
length:255,
name:"picture",
comment:"图片"
})
picture:string;
@Column({
type:"text",
nullable:true,
name:"content",
comment:"内容"
})
content:string;
@CreateDateColumn({
type:"timestamp",
nullable:false,
name:"create_time",
comment:"创建时间"
})
createTime:Date;
@UpdateDateColumn({
type:"timestamp",
nullable:false,
name:"update_time",
comment:"更新时间"
})
updateTime:Date;
@ManyToOne((type) => User, (user) => user.article)
user:User;
}
在User表中我们需要添加一个字段
@OneToMany((type)=> Article,article=>article.user)
article:Article[]
向表中添加数据后我们就可以查询了
createConnection().then(async connection => {
const userRepository = connection.getRepository(User);
const result = await userRepository.find({ relations: ["article"] });
console.log(result);
}).catch(error => console.log(error));
或者反向查询
createConnection().then(async connection => {
const articleRepository = connection.getRepository(Article);
const result = await articleRepository.find({ relations: ["user"] });
console.log(result);
}).catch(error => console.log(error));
结果:
- 多对多
一篇文章通常不只一个标签,而一个标签不只对应一篇文章这就是多对多的关系,一般多对多的关系都会用中间表来关联,所以我们需要创建一个中间表。
Tag.ts
import { Column,Entity, ManyToMany, PrimaryGeneratedColumn } from "typeorm";
import { Article } from "./Article";
@Entity()
export class Tag {
@PrimaryGeneratedColumn({
type:'int',
name:'id',
comment:'主键id'
})
id:number;
@Column({
type:'varchar',
length:50,
name:'tagName',
comment:'标签名'
})
tagName:string;
@ManyToMany((type) => Article, (article) => article.tag)
@JoinTable({name: 'article_tag'})
article:Article[];
}
Article.ts
增加多对多的字段
@ManyToMany((type) => Tag, (tag) => tag.article)
tag: Tag[];
添加完字段后在控制台中输入npm start数据库的表就会增加tag和article_tag的表
接下来就可以简单往表里填充数据
createConnection().then(async connection => {
const articleRepository = connection.getRepository(Article);
// relations存放一个数组,可以存放多个关联关系的
const result = await articleRepository.findOne({where: {id:2},relations: ["tag","user"]});
console.log(result);
}).catch(error => console.log(error));
运行的效果: