TypeORM是一个ORM (opens new window)框架,它可以运行在 NodeJS、Browser、Cordova、PhoneGap、Ionic、React Native、Expo和Electron平台上,可以与TypeScript 和 JavaScript (ES5,ES6,ES7,ES8)一起使用。 它的目标是始终支持最新的JavaScript特性并提供额外的特性以帮助你开发任何使用数据库的(不管是只有几张表的小型应用还是拥有多数据库的大型企业应用)应用程序。JavaScript ORM框架,TypeORM支持Active Record和Data Mapper模式,这意味着你可以以最高效的方式编写高质量的、松耦合的、可扩展的、可维护的应用程序。DataMapper 和 ActiveRecord (随你选择)QueryBuilderjson / xml / yml / env 格式的连接配置MySQL / MariaDB / Postgres / SQLite / Microsoft SQL Server / Oracle / sql.jsMongoDB NoSQL 数据库NodeJS / 浏览器 / Ionic / Cordova / React Native / Expo / Electron 平台上使用TypeScript 和 JavaScriptnpm安装:
npm install typeorm --savereflect-metadata:
npm install reflect-metadata --saveapp.ts中)
import "reflect-metadata";node typings(以此来使用Node的智能提示):
npm install @types/node –saveMySQL
npm install mysql --save(也可以安装mysql2)TypeScript编译器版本2.3或更高版本,并且已经在tsconfig.json中启用了以下设置:
"emitDecoratorMetadata": true,"experimentalDecorators": true,@types安装es6-shim开始使用TypeORM的最快方法是使用其CLI命令(脚手架)生成启动项目。 只有在NodeJS应用程序中使用TypeORM时,此操作才有效。
首先全局安装TypeORM:
npm install typeorm –g

然后转到要创建新项目的目录并运行命令:
typeorm init --name LearnTypeorm --database mysql

其中name是项目的名称,database是您将使用的数据库。
mysql, mariadb, postgres, sqlite, mssql, oracle, mongodb, cordova, react-native, expo, nativescript.node项目上运行typeorm init,但要注意,此操作可能会覆盖已有的某些文件。然后用编辑软件打开创建好的项目,会先出现一个md说明文件

第一步:npm i

第二步:删掉src文件夹下面的migration文件
第三步:配置tsconfig.json文件(把"module":"ESNext"换成"module": "CommonJS")

第四步:配置ormconfig.json

{
"type": "mysql",
"host": "localhost",
"port": 3306,
"username": "root",
"password": "123456",
"database": "mall",
"synchronize": true,
"logging": false,
"entities": [
"src/entity/**/*.ts"
],
"cli": {
"entitiesDir": "src/entity"
}
}
package.json)注意版本:下面的文件如果执行出现错误,可能是你的包版本太高导致的
{
"name": "learn_typeorm",
"version": "0.0.1",
"description": "Awesome project developed with TypeORM.",
"devDependencies": {
"ts-node": "3.3.0",
"@types/node": "^8.0.29",
"typescript": "3.3.3333"
},
"dependencies": {
"mysql": "^2.14.1",
"reflect-metadata": "^0.1.10",
"ts-node-dev": "^1.1.8",
"typeorm": "0.2.37"
},
"scripts": {
"start": "ts-node-dev src/find进阶选项.ts"
}
}
TypeORM支持多个配置源。你只需要在应用程序的根目录(package.json附近)中创建一个ormconfig.[format]文件存放连接配置,并在应用程序中调用createConnection(),而不传递任何参数配置ormconfig 文件格式有:.json, .js, .env, .yml和.xmlgetConnectionOptions()或尝试在没有连接选项的情况下使用createConnection()时,Typeorm将尝试按以下顺序加载配置:ormconfig.[format]文件,按此顺序:[js,ts,json,yml,yaml,xml]。Typeorm将使用找到的第一个有效方法,而不会加载其他方法。 例如,如果在环境中找到配置,Typeorm将不会加载ormconfig.[format]文件。createConnection或在ormconfig文件中定义的连接配置。不同的数据库有自己的特定连接选项。type - 数据库类型。你必须指定要使用的数据库引擎。该值可以是"mysql...."。此选项是必需的。name - 连接名。 在使用 getConnection(name: string) 或 ConnectionManager.get(name: string)时候需要用到。不同连接的连接名称不能相同,它们都必须是唯一的。如果没有给出连接名称,那么它将被设置为"default"。entities - 要加载并用于此连接的实体。接受要加载的实体类和目录路径。目录支持 glob 模式。示例:entities: [Post, Category, "entity/*.js", "modules/**/entity/*.js"]。subscribers - 要加载并用于此连接的订阅者。接受要加载的实体类和目录。migrations - 要加载和用于此连接的迁移。接受要加载的迁移类和目录logging - 指示是否启用日志记录。如果设置为true,则将启用查询和错误日志记录。你还可以指定要启用的不同类型的日志记录,例如["query", "error", "schema"]maxQueryExecutionTime - 如果查询执行时间超过此给定的最大执行时间(以毫秒为单位),则 logger 将记录此查询。entityPrefix - 给此数据库连接上的所有表(或集合)加的前缀。dropSchema - 每次建立连接时删除架构。请注意此选项,不要在生产环境中使用它,否则将丢失所有生产数据。但是此选项在调试和开发期间非常有用。synchronize - 指示是否在每次应用程序启动时自动创建数据库架构。 请注意此选项,不要在生产环境中使用它,否则将丢失所有生产数据。但是此选项在调试和开发期间非常有用。cache - 启用实体结果缓存。cli.entitiesDir - CLI 默认情况下创建实体的目录。cli.migrationsDir - CLI 默认情况下创建迁移的目录。cli.subscribersDir - CLI 默认情况下创建订阅者的目录。从ormconfig文件加载所有连接选项
import 'reflect-metadata'
import {createConnection} from "typeorm";
import {User} from "./entity/User";
const getConnection = async ()=>{
// 创建数据库连接
const connection = await createConnection()
console.log(connection)
}
getConnection()
Repository就像EntityManager一样,但其操作仅限于具体实体。
// User.ts
import { Entity, PrimaryGeneratedColumn, Column } from "typeorm"
@Entity()
export class User {
@PrimaryGeneratedColumn()
id: number
@Column()
firstName: string
@Column()
lastName: string
@Column()
age: number
// 构造函数
constructor(firstName: string, lastName: string, age: number,id?:number) {
this.firstName = firstName;
this.lastName = lastName;
this.age = age;
this.id = id
}
}
// index.ts
import 'reflect-metadata'
import {createConnection, getManager} from "typeorm";
import {User} from "./entity/User";
createConnection().then(()=>{
// 获取实体管理器
const entityManger = getManager()
/**
* 添加
*/
const save = async ()=>{
const user:User = new User('张','三',20)
// 通过实体管理器添加用户
const res = await entityManger.save<User>(user)
console.log(res)
}
// save()
/**
* 查询所有
*/
const queryAll = async ()=>{
// 查询全部
const [users]:User[] = await entityManger.find<User>(User)
console.log(users)
}
// queryAll()
/**
* 修改
*/
const edit = async () => {
const user:User = new User('李','四',20,1)
const res = await entityManger.save<User>(user)
console.log(res)
}
// edit()
/**
* 删除
*/
const del = async ()=>{
const {affected} = await entityManger.delete<User>(User,[3,4])
console.log(affected?'删除成功':'删除失败')
}
// del()
})
Repository就像EntityManager一样,但其操作仅限于具体实体。
// User.ts
import { Entity, PrimaryGeneratedColumn, Column } from "typeorm"
@Entity()
export class User {
@PrimaryGeneratedColumn()
id: number
@Column()
firstName: string
@Column()
lastName: string
@Column()
age: number
// 构造函数
constructor(firstName: string, lastName: string, age: number,id?:number) {
this.firstName = firstName;
this.lastName = lastName;
this.age = age;
this.id = id
}
}
// index.ts
import 'reflect-metadata'
import {createConnection, getRepository} from "typeorm";
import {User} from "./entity/User";
/**
* Repository
*/
createConnection().then((connection)=>{
// 获取存储库
const userRepository = getRepository(User)
/**
* 添加
*/
const save = async ()=>{
const user:User = new User('刘','能',30)
const res = await userRepository.save(user)
console.log(res)
}
// save()
/**
* 查询所有
*/
const queryAll = async ()=>{
const users:User[] = await userRepository.find()
console.log(users)
}
// queryAll()
/**
* 修改
*/
const edit = async () => {
const user:User = new User('刘','能',11,7)
const res = await userRepository.save(user)
console.log(res)
}
// edit()
/**
* 删除
*/
const del = async ()=>{
const {affected} = await userRepository.delete(5)
console.log(affected?'删除成功':'删除失败')
}
del()
})
可以创建一个自定义存储库,其中应包含使用数据库的方法。 通常为单个实体创建自定义存储库,并包含其特定的查询
import "reflect-metadata"; // 使用装饰器需要导入
import {EntityRepository, Repository, getCustomRepository, createConnection} from 'typeorm';
import {User} from "./entity/User";
// 装饰器 自定义的用户存储库存储库
@EntityRepository(User)
class UserRepository extends Repository<User>{
// 自定义的方法
findByName(firstName: string, lastName: string) {
return this.findOne({firstName,lastName})
}
}
createConnection().then(()=>{
// 获取自定义的存储库的实例 参数就是自定义的存储库
const userRepository= getCustomRepository(UserRepository)
// const save = async()=>{
// const user:User = new User('王','五',18)
// const res = await userRepository.save(user)
// console.log(res)
// }
// save()
const queryByName = async ()=>{
const user = await userRepository.findByName('王','五')
console.log(user)
}
queryByName()
})
所有存储库和管理器find方法都接受可用于查询所需数据的特殊选项,而无需使用QueryBuilder
// index.ts
import "reflect-metadata";
import {createConnection, getRepository} from "typeorm";
import {User} from "./entity/User"; // 使用装饰器需要导入
createConnection().then(async ()=>{
const userRepository = getRepository(User)
const res = await userRepository.find({
// 限制查询字段
select:['id','firstName','lastName','age'],
// 查询条件
// where:{firstName:'张'}
// or 使用数组
where:[{firstName:'张'},{firstName: '刘'}],
// order 排序
// ASC 1 升序
// DESC -1 降序
order:{id:'DESC'},
// 分页
// skip 起始位置
skip:0,
// take 数量
take:1,
// 是否开启缓存
cache:true
})
console.log(res)
})
TypeORM提供了许多内置运算符,可用于创建更复杂的查询
import "reflect-metadata";
import {
createConnection,
getRepository,
LessThan,
LessThanOrEqual,
Not,
MoreThan,
MoreThanOrEqual,
Equal, Like, Between, In
} from "typeorm";
import {User} from "./entity/User";
/**
* find 选项 - 进阶
*/
// 创建数据库连接
createConnection().then(async()=> {
// 获取用户的存储库
const userRepository = getRepository(User)
// Not:SELECT * FROM "user" WHERE "firstName" != '张';
// user 表中不含有 firstName 为 张 的
const users: User[] = await userRepository.find({
firstName:Not('张')
})
console.log("不信张的列表",users)
// LessThan:SELECT * FROM "user" WHERE "age" < 15
// user 表中 age 小于 15 的列表
const users1: User[] = await userRepository.find({
age:LessThan(15)
})
console.log("年龄小于15的列表",users1)
// LessThanOrEqual:SELECT * FROM "user" WHERE "age" <= 11
// user 表中 age 小于等于 11 的列表
const users2: User[] = await userRepository.find({
age:LessThanOrEqual (11)
})
console.log("年龄小于等于11的列表",users2)
// MoreThan:SELECT * FROM "user" WHERE "age" > 10
// user 表中 age 大于 10 的列表
const users3: User[] = await userRepository.find({
age:MoreThan (10)
})
console.log("年龄大于10的列表",users3)
// MoreThanOrEqual: SELECT * FROM "user" WHERE "age" > = 20
// user 表中 age 大于等于 20 的列表
const users4: User[] = await userRepository.find({
age:MoreThanOrEqual (20)
})
console.log("年龄大于等于20的列表",users4)
// Equal: SELECT * FROM "user" WHERE "age" = 11
// user 表中 age 大于等于 20 的列表
const users5: User[] = await userRepository.find({
age:Equal (11)
})
console.log("年龄等于11的列表",users5)
// Like:SELECT * FROM "user" WHERE "firstName" LIKE '%张%'
// 模糊查询 user 表中 firstName 姓 张 的列表
const users6: User[] = await userRepository.find({
firstName:Like ('%张%')
})
console.log("模糊查询姓张的列表",users6)
// Between:SELECT * FROM "user" WHERE "age" BETWEEN 1 AND 10
// 查询 user 表中 age 在 1 到 11 之间的 包括1和11
const users7: User[] = await userRepository.find({
age:Between (1,11)
})
console.log("查询年龄1到11之间的",users7)
// In: SELECT * FROM "user" WHERE "age" IN (11,20)
// 查询 user 表中 age 在 11和20
const users8: User[] = await userRepository.find({
age:In([11,20])
})
console.log(users8)
})
实体:是一个映射到数据库表的类。 你可以通过定义一个新类来创建一个实体,并用@Entity()来标记
实体列:由于数据库表由列组成,因此实体也必须由列组成。 标有@Column的每个实体类属性都将映射到数据库表列
主列:每个实体必须至少有一个主列。有几种类型的主要列:
@PrimaryColumn()创建一个主列,它可以获取任何类型的任何值。你也可以指定列类型。 如果未指定列类型,则将从属性类型自动推断。@PrimaryGeneratedColumn()创建一个主列,该值将使用自动增量值自动生成。@PrimaryGeneratedColumn("uuid")创建一个主列,该值将使用uuid自动生成,(Uuid 是一个独特的字符串id)特殊列:
@CreateDateColumn自动为实体插入日期。无需设置此列,该值将自动设置。@UpdateDateColumn在每次调用实体管理器或存储库的save时,自动更新实体日期。无需设置此列,该值将自动设置。列类型
@Column(“int”)或者@Column({ type: "int" })@Column("varchar", { length: 200 })import {Column, CreateDateColumn, Entity, PrimaryGeneratedColumn, UpdateDateColumn} from "typeorm";
/**
* 实体类 => 数据库表
* 添加了 @Entity 装饰器就会被 typeorm 去映射,判断表是否存在,不存在表才会被创建,存在不做处理
* 你要想创建类的表结构,就需要创建 @Entity()
*/
@Entity()
export default class Person {
// 主键:PrimaryColumn
// @PrimaryGeneratedColumn('uuid') 传入uuid会自动生成uuid作为主键
// 自动增长的主键
@PrimaryGeneratedColumn()
id:number
// 自动添加创建时间
@CreateDateColumn()
createAt:Date
// 自动修改时间
@UpdateDateColumn()
updateAt:Date
// 列 name varchar(255)
// 添加了 @Column() 会映射为表中的字段
// 可以指定列的类型 也可以限制长度
@Column('varchar',{length:20})
name:string
// 可以指定列的类型
@Column('int')
gander:number
constructor(name: string) {
this.name = name;
}
}
int, tinyint, smallint, mediumint, bigint, float, double, dec, decimal, numeric, date, datetime, timestamp, time, year, char, varchar, nvarchar, text, tinytext, mediumtext, blob, longtext, tinyblob, mediumblob, longblob, enum, json, binary, geometry, point, linestring, polygon, multipoint, multilinestring, multipolygon, geometrycollection
enum列类型
import {Column, CreateDateColumn, Entity, PrimaryGeneratedColumn, UpdateDateColumn} from "typeorm";
export enum PersonRole {
STUDENT = 'student',
TEACHER = 'teacher'
}
/**
* 实体类 => 数据库表
* 添加了 @Entity 装饰器就会被 typeorm 去映射,判断表是否存在,不存在表才会被创建,存在不做处理
* 你要想创建类的表结构,就需要创建 @Entity()
*/
@Entity()
export default class Person {
// 主键:PrimaryColumn
// @PrimaryGeneratedColumn('uuid') 传入uuid会自动生成uuid作为主键
// 自动增长的主键
@PrimaryGeneratedColumn()
id:number
// 自动添加创建时间
@CreateDateColumn()
createAt:Date
// 自动修改时间
@UpdateDateColumn()
updateAt:Date
// 列 name varchar(255)
// 添加了 @Column() 会映射为表中的字段
// 可以指定列的类型 也可以限制长度
@Column('varchar',{length:20})
name:string
// 可以指定列的类型
@Column('int')
gander:number
@Column({
type:"enum",
enum:PersonRole
})
role:PersonRole
constructor(name: string, gander: number, role: PersonRole) {
this.name = name;
this.gander = gander;
this.role = role;
}
}
simple-array的列类型: 它可以将原始数组值存储在单个字符串列中。 所有值都以逗号分隔。 返回时,也将作为数组方式返回
import {Column, CreateDateColumn, Entity, PrimaryGeneratedColumn, UpdateDateColumn} from "typeorm";
export enum PersonRole {
STUDENT = 'student',
TEACHER = 'teacher'
}
/**
* 实体类 => 数据库表
* 添加了 @Entity 装饰器就会被 typeorm 去映射,判断表是否存在,不存在表才会被创建,存在不做处理
* 你要想创建类的表结构,就需要创建 @Entity()
*/
@Entity()
export default class Person {
// 主键:PrimaryColumn
// @PrimaryGeneratedColumn('uuid') 传入uuid会自动生成uuid作为主键
// 自动增长的主键
@PrimaryGeneratedColumn()
id:number
// 自动添加创建时间
@CreateDateColumn()
createAt:Date
// 自动修改时间
@UpdateDateColumn()
updateAt:Date
// 列 name varchar(255)
// 添加了 @Column() 会映射为表中的字段
// 可以指定列的类型 也可以限制长度
@Column('varchar',{length:20})
name:string
// 可以指定列的类型
@Column('int')
gander:number
@Column({
type:"enum",
enum:PersonRole
})
role:PersonRole
@Column({
// 列是一个数组
type:'simple-array'
})
nickName:Array<string>
constructor(name: string, gander: number, role: PersonRole) {
this.name = name;
this.gander = gander;
this.role = role;
}
}
simple-json列类型:可以存储任何可以通过JSON.stringify存储在数据库中的值。 当你的数据库中没有json类型而你又想存储和加载对象,该类型就很有用了
import {Column, CreateDateColumn, Entity, PrimaryGeneratedColumn, UpdateDateColumn} from "typeorm";
export enum PersonRole {
STUDENT = 'student',
TEACHER = 'teacher'
}
/**
* 实体类 => 数据库表
* 添加了 @Entity 装饰器就会被 typeorm 去映射,判断表是否存在,不存在表才会被创建,存在不做处理
* 你要想创建类的表结构,就需要创建 @Entity()
*/
@Entity()
export default class Person {
// 主键:PrimaryColumn
// @PrimaryGeneratedColumn('uuid') 传入uuid会自动生成uuid作为主键
// 自动增长的主键
@PrimaryGeneratedColumn()
id:number
// 自动添加创建时间
@CreateDateColumn()
createAt:Date
// 自动修改时间
@UpdateDateColumn()
updateAt:Date
// 列 name varchar(255)
// 添加了 @Column() 会映射为表中的字段
// 可以指定列的类型 也可以限制长度
@Column('varchar',{length:20})
name:string
// 可以指定列的类型
@Column('int')
gander:number
@Column({
type:"enum",
enum:PersonRole
})
role:PersonRole
@Column({
// 列是一个数组
type:'simple-array'
})
nickName:Array<string>
@Column('simple-json')
perfile:{name:string,nickName:string}
constructor(name: string, gander: number, role: PersonRole) {
this.name = name;
this.gander = gander;
this.role = role;
}
}
列选项定义实体列的其他选项。 你可以在@Column上指定列选项:
ColumnOptions中可用选项列表:
type: ColumnType - 列类型。
name: string - 数据库表中的列名。默认情况下,列名称是从属性的名称生成的。 你也可以通过指定自己的名称来更改它。
length: number - 列类型的长度。 例如,如果要创建varchar(150)类型,请指定列类型和长度选项。
nullable: boolean - 在数据库中使列NULL或NOT NULL。 默认情况下,列是nullable:false。
update: boolean - 指示"save"操作是否更新列值。如果为false,则只能在第一次插入对象时编写该值。 默认值为"true"。
select: boolean - 定义在进行查询时是否默认隐藏此列。 设置为false时,列数据不会显示标准查询。 默认情况下,列是select:true
default: string - 添加数据库级列的DEFAULT值。
primary: boolean - 将列标记为主要列。 使用方式和@PrimaryColumn相同。
unique: boolean- 将列标记为唯一列(创建唯一约束)。
comment: string - 数据库列备注,并非所有数据库类型都支持。
enum: string[]|AnyEnum - 在enum列类型中使用,以指定允许的枚举值列表。 你也可以指定数组或指定枚举类。
import {Column, Entity, PrimaryGeneratedColumn} from "typeorm";
@Entity()
export class Student {
@PrimaryGeneratedColumn()
id:number
@Column({
// 自定义字段的类型
type:'varchar',
// 自定义字段的名称
name:'sname',
// 自定义字段的长度
length:20,
// not null 允许为空 false 不为空
nullable:true,
update:true,
// false 查询时不显示
select:false,
// 列的默认值
default:'123',
// 唯一约束
unique:false,
// 列的注释
comment:'姓名',
})
name:string
constructor(name: string) {
this.name = name;
}
}
import 'reflect-metadata'
import {createConnection, getRepository} from "typeorm";
import {Student} from "./entity/Student";
createConnection().then(async ()=>{
const studentRepository = getRepository(Student)
// 添加
const stu = new Student('张三')
await studentRepository.save(stu)
// 查询
const student:Student[] = await studentRepository.find()
console.log(student)
})
embedded columns,可以减少应用程序中的重复@OneToOne@ManyToOne@OneToMany@ManyToManyeager: boolean - 如果设置为true,则在此实体上使用find * 或QueryBuilder时,将始终使用主实体加载关系cascade: boolean - 如果设置为true,则将插入相关对象并在数据库中更新。onDelete: "RESTRICT"|"CASCADE"|"SET NULL" - 指定删除引用对象时外键的行为方式primary: boolean - 指示此关系的列是否为主列。nullable: boolean -指示此关系的列是否可为空。 默认情况下是可空。orphanedRowAction: "nullify" | "delete" - 将子行从其父行中删除后,确定该子行是孤立的(默认值)还是删除的。一对一是一种A只包含一个B实例,而B只包含一个A实例的关系。 我们以Users和Profile实体为例。
用户只能拥有一个配置文件,并且一个配置文件仅由一个用户拥有。
// Profile.ts
import {Column, Entity, PrimaryGeneratedColumn} from "typeorm";
@Entity()
export class Profile {
@PrimaryGeneratedColumn()
id:number
@Column()
gander:number
constructor(gander: number) {
this.gander = gander;
}
}
// Users.ts
import {Column, Entity, JoinColumn, OneToOne, PrimaryGeneratedColumn} from "typeorm";
import {Profile} from "./Profile";
@Entity()
export class Users {
@PrimaryGeneratedColumn()
id:number
@Column()
name:string
// OneToOne 一对一 指定关系
@OneToOne(()=>Profile)
// 外键
@JoinColumn()
profile:Profile
constructor(name: string, profile: Profile) {
this.name = name;
this.profile = profile;
}
}
这里我们将@OneToOne添加到profile并将目标关系类型指定为Profile。 我们还添加了@JoinColumn,这是必选项并且只能在关系的一侧设置。你设置@JoinColumn的哪一方,哪一方的表将包含一个"relation id"和目标实体表的外键。
同样,@JoinColumn必须仅设置在关系的一侧且必须在数据库表中具有外键的一侧。
// 一对一.ts
import {createConnection, getRepository} from "typeorm";
import {Profile} from "./entity/Profile";
import {Users} from "./entity/Users";
createConnection().then(()=>{
const usersRepository = getRepository(Users)
const profileRepository = getRepository(Profile)
const save = async ()=>{
// 创建 profile 对象
const profile = new Profile(20)
// 添加 profile 信息到数据库
await profileRepository.save(profile)
// 创建 users 对象
const users = new Users('张三',profile)
// 添加 users 信息到数据库
const res = await usersRepository.save(users)
console.log(res)
}
// save()
// 查询
const queryOne = async () =>{
const users = await usersRepository.findOne({
relations:['profile'],
where:{id:1}
})
console.log(users)
}
queryOne()
})
多对一/一对多是指A包含多个B实例的关系,但B只包含一个A实例。 让我们以User和Photo 实体为例。 User可以拥有多张photos,但每张photo仅由一位user拥有
// Photo.ts
import {Column, Entity, ManyToOne, PrimaryGeneratedColumn} from "typeorm";
import {User} from "./User";
@Entity()
export class Photo{
@PrimaryGeneratedColumn()
id:number
@Column()
url:string
@ManyToOne(()=>User,person =>person.photos)
person:User
constructor(url: string) {
this.url = url;
}
}
// User.ts
import {Column, Entity, OneToMany, PrimaryGeneratedColumn} from "typeorm";
import {Photo} from "./Photo";
@Entity()
export class User {
@PrimaryGeneratedColumn()
id:number
@OneToMany(()=>Photo,photo=> photo.person)
photos:Photo[]
constructor(photos: Photo[]) {
this.photos = photos;
}
}
这里我们将@OneToMany添加到photos属性中,并将目标关系类型指定为Photo。 你可以在@ManyToOne / @OneToMany关系中省略@JoinColumn,除非你需要自定义关联列在数据库中的名称。 @ManyToOne可以单独使用,但@OneToMany必须搭配@ManyToOne使用。 如果你想使用
@OneToMany,则需要@ManyToOne。 在你设置@ManyToOne的地方,相关实体将有"关联 id"和外键。
需要查询带有photos的user,必须在FindOptions中指定关系
import {createConnection, getRepository} from "typeorm";
import {User} from "./entity/User";
import {Photo} from "./entity/Photo";
createConnection().then(()=>{
const userRepository = getRepository(User)
const photoRepository = getRepository(Photo)
const save = async () => {
const photo1 = new Photo('./img/01.jpg')
const photo2 = new Photo('./img/02.jpg')
await photoRepository.save([photo1,photo2])
const user = new User([photo1,photo2])
const res = await userRepository.save(user)
console.log(res)
}
// save()
const queryAll = async () =>{
const res = await userRepository.find({
relations:['photos']
})
console.log(res)
}
queryAll()
})
多对多是一种A包含多个B实例,而B包含多个A实例的关系。 我们以Question和Category实体为例。 Question可以有多个 categories, 每个category可以有多个questions
// Category 类别
import {Column, Entity, PrimaryGeneratedColumn} from "typeorm";
@Entity()
export class Category {
@PrimaryGeneratedColumn()
id:number
@Column()
name:string
constructor(name: string) {
this.name = name;
}
}
// Question 问题
import {Column, Entity, JoinTable, ManyToMany, PrimaryGeneratedColumn} from "typeorm";
import {Category} from "./Category";
@Entity()
export class Question {
@PrimaryGeneratedColumn()
id:number
@Column()
title:string
@Column()
text:string
@ManyToMany(()=>Category)
@JoinTable()
categories:Category[]
constructor(title: string, text: string, categories: Category[]) {
this.title = title;
this.text = text;
this.categories = categories;
}
}
@JoinTable()是@ManyToMany关系所必需的
要在categories里面加载question,你必须在FindOptions中指定关系
import {createConnection, getRepository} from "typeorm";
import {Category} from "./entity/Category";
import {Question} from "./entity/Question";
createConnection().then(()=>{
const categoryRepository = getRepository(Category)
const questionRepository = getRepository(Question)
const save = async () =>{
const category1 = new Category('animals')
const category2 = new Category('zoo ')
await categoryRepository.save([category1,category2])
const question = new Question('标题','文本',[category1,category2])
const res = await questionRepository.save(question)
console.log(res)
}
// save()
const queryAll = async ()=>{
const res = await questionRepository.find({
relations:['categories']
})
console.log(res)
}
queryAll()
})
QueryBuilder是TypeORM最强大的功能之一 ,它允许你使用优雅便捷的语法构建SQL查询,执行并获得自动转换的实体。npm install typeorm-model-generator typeorm-model-generator -h localhost -d mall -u root -x 123456 -e mysql -o entity
-h localhost -d 数据库名字 -p 端口 -u 用户名 -x 密码 -e 数据库类型-o entities表示输出到指定的文件夹