前言
一对一
一般情况一对一要创建双向关系,以上次创建的user表为例,额外新增user的扩展表user_extend:
import {
Entity,
PrimaryGeneratedColumn,
Column,
OneToOne,
JoinColumn,
} from "typeorm" ;
import { User } from "./User" ;
@Entity ( { name: "user_extend" } )
export class UserExtend {
@PrimaryGeneratedColumn ( {
type : "int" ,
name: "id" ,
comment: "主键id" ,
} )
id: number ;
@Column ( {
type : "varchar" ,
length: 11 ,
nullable: true ,
name: "mobile" ,
comment: "手机号码" ,
} )
mobile: string ;
@Column ( {
type : "varchar" ,
length: 50 ,
nullable: true ,
name: "address" ,
comment: "地址" ,
} )
address: string ;
@OneToOne ( ( type ) => User, ( user) => user. userDetail)
@JoinColumn ( )
user: User;
}
关键在最下面3行,一个是调用了OneToOne与User表的userDetail进行关联,使用JoinColumn与User表进行关联。如果是单项关系,OneToOne第二个参数可以不传。 同时,User表新建字段userDetail:
@OneToOne ( ( type ) => UserExtend, ( userExtend) => userExtend. user)
@JoinColumn ( )
userDetail: UserExtend;
插入数据有点不一样就是做个关联,然后有个保存顺序。
createConnection ( ) . then ( async connection => {
const user = new User ( ) ;
user. username = '王五' ;
user. password = '123456' ;
const userExtend = new UserExtend ( ) ;
userExtend. mobile = '13412345678' ;
userExtend. address = '中国' ;
userExtend. user = user;
const userRepository = connection. getRepository ( User) ;
await userRepository. save ( user) ;
const userExtendRepository = connection. getRepository ( UserExtend) ;
await userExtendRepository. save ( userExtend) ;
console . log ( '插入数据成功' ) ;
} ) . catch ( error => console . log ( error) ) ;
查询:这个result是user表有userDetail字段的。
const userRepository = connection. getRepository ( User) ;
const result = await userRepository. find ( { relations: [ "userDetail" ] } ) ;
反向查询:取得是user扩展表,其字段user关联user表。
const userExtendRepository = connection. getRepository ( UserExtend) ;
const result = await userExtendRepository. find ( { relations: [ "user" ] } ) ;
console . log ( result) ;
一对多
import {
Entity,
PrimaryGeneratedColumn,
Column,
CreateDateColumn,
UpdateDateColumn,
} from "typeorm" ;
@Entity ( { name: "posts" } )
export class Posts {
@PrimaryGeneratedColumn ( {
type : "int" ,
name: "id" ,
comment: "主键id" ,
} )
id: number ;
@Column ( {
type : "varchar" ,
nullable: false ,
length: 50 ,
unique: true ,
name: "title" ,
comment: "标题" ,
} )
title: string ;
@Column ( {
type : "text" ,
nullable: true ,
name: "content" ,
comment: "内容" ,
} )
content: string ;
@Column ( "tinyint" , {
nullable: false ,
default : ( ) => 0 ,
name: "is_del" ,
comment: "是否删除,1表示删除,0表示正常" ,
} )
isDel: number ;
@CreateDateColumn ( {
type : "timestamp" ,
nullable: false ,
name: "created_at" ,
comment: "创建时间" ,
} )
createdAt: Date;
@UpdateDateColumn ( {
type : "timestamp" ,
nullable: false ,
name: "updated_at" ,
comment: "更新时间" ,
} )
updateAt: Date;
}
同样的,两边都加上ManyToOne和OneToMany :
@ManyToOne ( ( type ) => User, ( user) => user. posts)
user: User;
@OneToMany ( ( type ) => Posts, ( post) => post. user)
posts: Posts[ ] ;
oneToOne需要加column ,而OneToMany会自动加列,可以不用加。 查询:
const userRepository = connection. getRepository ( User) ;
const result = await userRepository. find ( { relations: [ "posts" ] } ) ;
console . log ( result) ;
const postsRepository = connection. getRepository ( Posts) ;
const result = await postsRepository. find ( { relations: [ "user" ] } ) ;
console . log ( result) ;
多对多
一般都是构建一张中间表来存放两个表的主键,当要更新一个数据的时候会先去中间表中根据条件删除之前的数据,然后重新添加进去。 这里以一个帖子可能有多个tag ,多个tag可能对应一个帖子为例:
import {
Entity,
PrimaryGeneratedColumn,
Column,
ManyToMany,
JoinTable,
} from "typeorm" ;
import { Posts } from "./Posts" ;
@Entity ( "tags" )
export class Tags {
@PrimaryGeneratedColumn ( {
type : "int" ,
name: "id" ,
comment: "主键id" ,
} )
id: number ;
@Column ( {
type : "varchar" ,
name: "name" ,
nullable: false ,
unique: true ,
comment: "tag名称" ,
} )
name: string ;
@ManyToMany ( ( type ) => Posts, ( post) => post. tags)
@JoinTable ( { name: "tags_posts" } )
posts: Posts[ ] ;
}
@ManyToMany ( ( type ) => Tags, ( tag) => tag. posts)
tags: Tags[ ] ;
运行后发现多了个中间表tags_posts以及tags表。 创建表:
const tag1 = new Tags ( ) ;
tag1. name = "mysql" ;
const tag2 = new Tags ( ) ;
tag2. name = "node" ;
const posts1 = new Posts ( ) ;
posts1. title = "文章一" ;
posts1. content = "文章一内容" ;
posts1. tags = [ tag1, tag2] ;
const posts2 = new Posts ( ) ;
posts2. title = "文章二" ;
posts2. content = "文章二内容" ;
posts2. tags = [ tag1] ;
const user = new User ( ) ;
user. username = "王五" ;
user. password = "123456" ;
user. posts = [ posts1, posts2] ;
const userRepository = connection. getRepository ( User) ;
const postsRepository = connection. getRepository ( Posts) ;
const tagRepository = connection. getRepository ( Tags) ;
await tagRepository. save ( tag1) ;
await tagRepository. save ( tag2) ;
await postsRepository. save ( posts1) ;
await postsRepository. save ( posts2) ;
await userRepository. save ( user) ;
console . log ( "添加数据成功" ) ;
const postsRepository = connection. getRepository ( Posts) ;
const result = await postsRepository. findOne ( { where: { id: 1 } , relations: [ 'tags' , 'user' ] } ) ;
console . log ( result) ;