环境搭建

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

  • TypeORM 支持 MySQL / MariaDB / Postgres / CockroachDB / SQLite / Microsoft SQL Server / Oracle / sql.js / MongoDB 数据库。

安装

npm egg-init --type=ts

npm install typeorm egg-ts-typeorm mysql2 --save

  • 配置 config/plugin.ts
export default {
  typeorm: {
    enable: true,
    package: 'egg-ts-typeorm',
  },
}
  • 配置 config/config.default.ts
config.typeorm = {
  client: {
    type: 'mysql',
    host: 'localhost',
    port: 3306,
    username: 'root',
    password: '123456',
    database: 'sq_test',
    synchronize: true,
    logging: true,
  },
}

// 关闭 csrf
config.security = {
  csrf: {
    enable: false,
  },
}
  • 根目录创建 ormconfig.yml 文件
default: # 默认连接
  entitiesdir: 'app/entities'
  • 创建 app/entities 文件夹

  • 创建 app/entities/User.ts 文件

import {
  Entity,
  PrimaryGeneratedColumn,
  Column,
  OneToMany,
  JoinColumn,
} from 'typeorm'
import Post from './Post'

@Entity()
import {
  Entity,
  PrimaryGeneratedColumn,
  Column,
  OneToMany,
  JoinColumn,
  OneToOne,
  ManyToMany,
  JoinTable,
} from 'typeorm'
import Post from './Post'
import Profile from './Profile'
import Course from './Course'

@Entity()
export default class User {
  @PrimaryGeneratedColumn({
    type: 'int',
    comment: '主键id',
  })
  id: number

  @Column({
    type: 'varchar',
    length: 50,
    comment: '账号',
  })
  account: string

  @Column({
    type: 'varchar',
    length: 50,
    comment: '密码',
  })
  password: string

  // 一对一
  @OneToOne(() => Profile)
  @JoinColumn()
  profile: Profile

  // 一对多
  @OneToMany(() => Post, (post) => post.user)
  @JoinColumn()
  posts: Post[]

  // 多对多
  @ManyToMany(() => Course)
  @JoinTable()
  courses: Course[]
}
  • 创建 app/entities/Profile.ts 文件
import { Entity, Column, PrimaryGeneratedColumn } from 'typeorm'

@Entity()
export default class Profile {
  @PrimaryGeneratedColumn({
    type: 'int',
    comment: '主键id',
  })
  id: number

  @Column({
    type: 'varchar',
    length: 50,
    comment: '姓名',
  })
  name: string

  @Column({
    type: 'int',
    comment: '年龄',
  })
  age: number

  @Column({
    type: 'varchar',
    length: 50,
    comment: '性别',
  })
  gender: string
}
  • 创建 app/entities/Course.ts 文件
import { Entity, PrimaryGeneratedColumn, Column } from 'typeorm'

@Entity()
export default class Course {
  @PrimaryGeneratedColumn({
    type: 'int',
    comment: '主键id',
  })
  id: number

  @Column({
    type: 'varchar',
    length: 50,
    comment: '课程名称',
  })
  name: string

  @Column({
    type: 'varchar',
    length: 50,
    comment: '课程描述',
  })
  description: string
}
  • 创建 app/entities/Post.ts 文件
import { Entity, PrimaryGeneratedColumn, Column, ManyToOne } from 'typeorm'
import User from './User'

@Entity()
export default class Post {
  @PrimaryGeneratedColumn({
    type: 'int',
    comment: '主键id',
  })
  id: number

  @Column({
    type: 'varchar',
    length: 50,
    comment: '标题',
  })
  title: string

  @Column({
    type: 'text',
    comment: '内容',
  })
  content: string

  // 关联用户 id
  @ManyToOne(() => User, (user) => user.posts)
  user: User
}

数据库操作

  • 创建 app/controller/user.ts 文件
import { Controller } from 'egg'
import User from '../entities/User'

export default class HomeController extends Controller {
  public async index() {
    const { ctx } = this
    // ctx.body = await ctx.repo.User.find({
    //   relations: ['posts'],
    // })
    // TypeORM 关系查询,只查部分字段该怎么写?
    // https://cnodejs.org/topic/5c3fe2bba4d44449266b1dce
    ctx.body = await ctx.repo.User.createQueryBuilder('user')
      .select([
        'user.id',
        'user.account',
        'profile.name',
        'profile.age',
        'profile.gender',
        'course.name',
        'course.description',
        'post.title',
        'post.content',
      ])
      .leftJoin('user.posts', 'post')
      .leftJoin('user.profile', 'profile')
      .leftJoin('user.courses', 'course')
      .getMany()
  }

  // 新增用户
  public async create() {
    const { ctx } = this
    // 个人信息
    const profile = new Profile()
    profile.name = '张三'
    profile.age = 18
    profile.gender = '男'
    await ctx.repo.Profile.save(profile)
    // 课程
    const course1 = new Course()
    course1.name = '语文'
    course1.description = '语文课程'
    await ctx.repo.Course.save(course1)

    const course2 = new Course()
    course2.name = '数学'
    course2.description = '数学课程'
    await ctx.repo.Course.save(course2)
    // 用户
    const user = new User()
    user.account = 'zhangsan'
    user.password = '123456'
    user.profile = profile
    user.courses = [course1, course2]
    await ctx.repo.User.save(user)

    ctx.body = '新增成功'
  }

  // 产找指定用户
  public async find() {
    const { ctx } = this
    ctx.body = await ctx.repo.User.findOne(ctx.params.id)
  }

  // 删除指定用户
  public async remove() {
    const { ctx } = this
    let userToRemove = await ctx.repo.User.findOne(ctx.params.id)
    await ctx.repo.User.remove(userToRemove)
    ctx.body = '删除成功'
  }
}
  • 创建 app/router.ts 文件
import { Controller } from 'egg'
import Post from '../entities/Post'

export default class PostController extends Controller {
  // 新增文章
  public async create() {
    const { ctx } = this
    let post = new Post()
    const { title, content, userId } = ctx.request.body
    post.title = title
    post.content = content
    // post.user = userId
    const user = await ctx.repo.User.findOne(userId)
    post.user = user

    ctx.body = await ctx.repo.Post.save(post)
  }
}

参考资料