Typeorm笔记

16 阅读4分钟

TypeORM 学习笔记

TypeORM 是一个流行的 TypeScript 和 JavaScript ORM(对象关系映射)框架,支持多种数据库,包括 MySQL、PostgreSQL、SQLite、SQL Server 等。本文将介绍 TypeORM 的基本概念、安装、配置和常用操作。

一、安装与配置

  1. 安装 TypeORM 和数据库驱动

首先,安装 TypeORM 和所需的数据库驱动。以 MySQL 为例:

npm install typeorm mysql2
  1. 创建配置文件

在项目根目录下创建 ormconfig.json 文件,配置数据库连接信息:

{
  "type": "mysql",
  "host": "localhost",
  "port": 3306,
  "username": "test",
  "password": "test",
  "database": "test",
  "synchronize": true,
  "logging": false,
  "entities": [
    "src/entity/**/*.ts"
  ],
  "migrations": [
    "src/migration/**/*.ts"
  ],
  "subscribers": [
    "src/subscriber/**/*.ts"
  ]
}

二、创建实体(Entity)

实体是 TypeORM 的核心概念,表示数据库中的表。每个实体类对应数据库中的一张表。

import { Entity, PrimaryGeneratedColumn, Column } from "typeorm";

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

  @Column()
  name: string;

  @Column()
  age: number;
}

三、连接数据库

在应用程序启动时连接数据库,可以在 src/index.ts 文件中实现:

import "reflect-metadata";
import { createConnection } from "typeorm";
import { User } from "./entity/User";

createConnection().then(async connection => {
  console.log("Connected to the database!");

  // 创建新的用户
  const user = new User();
  user.name = "John Doe";
  user.age = 25;

  // 保存用户
  await connection.manager.save(user);
  console.log("User has been saved.");

  // 查询用户
  const users = await connection.manager.find(User);
  console.log("Loaded users: ", users);
}).catch(error => console.log(error));

四、常用操作

  1. 插入数据

使用 save 方法插入或更新数据:

const user = new User();
user.name = "Jane Doe";
user.age = 30;
await connection.manager.save(user);
  1. 查询数据

使用 find 方法查询所有数据,findOne 方法查询单个数据:

const users = await connection.manager.find(User);
const user = await connection.manager.findOne(User, { where: { name: "Jane Doe" } });
  1. 更新数据

使用 save 方法更新数据:

const userToUpdate = await connection.manager.findOne(User, 1);
if (userToUpdate) {
  userToUpdate.age = 35;
  await connection.manager.save(userToUpdate);
}
  1. 删除数据

使用 remove 方法删除数据:

const userToRemove = await connection.manager.findOne(User, 1);
if (userToRemove) {
  await connection.manager.remove(userToRemove);
}

五、高级功能

  1. 关系(Relations)

TypeORM 支持实体之间的关系,如一对一、一对多、多对多。

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

  @Column()
  bio: string;

  @OneToOne(() => User)
  @JoinColumn()
  user: User;
}
  1. 迁移(Migrations)

迁移用于管理数据库的变更:

npx typeorm migration:generate -n CreateUserTable
npx typeorm migration:run

六、结论

TypeORM 是一个功能强大的 ORM 框架,适用于 TypeScript 和 JavaScript 应用程序。通过本文的介绍,你应该对如何安装、配置 TypeORM 以及如何进行基本的数据库操作有了初步的了解。进一步的学习可以参考 TypeORM 官方文档

旧数据库迁移到新数据

旧数据库已有数据时,通过已经存在的数据逆向形成实体类

使用库:typeorm-model-generator 支持常见的数据库(关系型数据库):

  • Microsoft SQL
  • PostgreSQL
  • MySQL
  • MariaDB
  • Oracle Database
  • SQLite

使用pnpm安装: pnpm i -D typeorm-model-generator

关系查询和分页

TypeORM 关系查询和分页详解

关系查询

TypeORM 提供了多种关系查询的 API 和关键词,帮助我们在进行复杂的数据查询时简化操作。以下是常用的 API 和关键词的含义及示例。

1. findOnefind
  • findOne:用于查询单个实体,根据条件返回一个实体对象或 undefined
  • find:用于查询多个实体,根据条件返回一个包含实体对象的数组。
2. relations
  • relations:一个包含关系名称的数组,用于指定要加载的相关实体。
3. 关系关键词
  • @OneToOne:一对一关系。
  • @OneToMany:一对多关系。
  • @ManyToOne:多对一关系。
  • @ManyToMany:多对多关系。
  • @JoinColumn:用于一对一和多对一关系,指定外键列。
  • @JoinTable:用于多对多关系,指定中间表。
示例:

一对一关系

// src/entity/User.ts
import { Entity, PrimaryGeneratedColumn, Column, OneToOne, JoinColumn } from "typeorm";
import { Profile } from "./Profile";

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

  @Column()
  name: string;

  @OneToOne(() => Profile, profile => profile.user)
  @JoinColumn()
  profile: Profile;
}

// src/entity/Profile.ts
import { Entity, PrimaryGeneratedColumn, Column, OneToOne } from "typeorm";
import { User } from "./User";

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

  @Column()
  bio: string;

  @OneToOne(() => User, user => user.profile)
  user: User;
}

进行关系查询:

const userRepository = connection.getRepository(User);
const userWithProfile = await userRepository.findOne({ where: { id: 1 }, relations: ["profile"] });
console.log(userWithProfile);

一对多关系

// src/entity/User.ts
import { Entity, PrimaryGeneratedColumn, Column, OneToMany } from "typeorm";
import { Post } from "./Post";

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

  @Column()
  name: string;

  @OneToMany(() => Post, post => post.user)
  posts: Post[];
}

// src/entity/Post.ts
import { Entity, PrimaryGeneratedColumn, Column, ManyToOne } from "typeorm";
import { User } from "./User";

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

  @Column()
  title: string;

  @ManyToOne(() => User, user => user.posts)
  user: User;
}

进行关系查询:

const userRepository = connection.getRepository(User);
const userWithPosts = await userRepository.findOne({ where: { id: 1 }, relations: ["posts"] });
console.log(userWithPosts);

多对多关系

// src/entity/Student.ts
import { Entity, PrimaryGeneratedColumn, Column, ManyToMany, JoinTable } from "typeorm";
import { Course } from "./Course";

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

  @Column()
  name: string;

  @ManyToMany(() => Course, course => course.students)
  @JoinTable()
  courses: Course[];
}

// src/entity/Course.ts
import { Entity, PrimaryGeneratedColumn, Column, ManyToMany } from "typeorm";
import { Student } from "./Student";

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

  @Column()
  title: string;

  @ManyToMany(() => Student, student => student.courses)
  students: Student[];
}

进行关系查询:

const studentRepository = connection.getRepository(Student);
const studentWithCourses = await studentRepository.findOne({ where: { id: 1 }, relations: ["courses"] });
console.log(studentWithCourses);

分页

分页是处理大数据量查询的重要手段。TypeORM 提供了分页查询的支持,常用的分页查询 API 和关键词如下:

  • findAndCount:返回一个数组,第一个元素是查询结果数组,第二个元素是满足条件的总数。
  • skip:跳过指定数量的结果。
  • take:限制返回结果的数量。
示例:

基本分页

const userRepository = connection.getRepository(User);
const page = 1;
const pageSize = 10;

const [users, total] = await userRepository.findAndCount({
  skip: (page - 1) * pageSize,
  take: pageSize,
});

console.log(users);
console.log(`Total users: ${total}`);

带条件的分页查询

const userRepository = connection.getRepository(User);
const page = 1;
const pageSize = 10;
const searchName = "John";

const [users, total] = await userRepository.findAndCount({
  where: { name: searchName },
  skip: (page - 1) * pageSize,
  take: pageSize,
});

console.log(users);
console.log(`Total users with name ${searchName}: ${total}`);

结论

通过本文的详细解释和示例代码,我们对 TypeORM 的关系查询和分页有了深入了解。利用这些功能,可以更高效地管理复杂数据查询和大数据量处理。更多详细信息可以参考 TypeORM 官方文档