TypeORM 学习笔记
TypeORM 是一个流行的 TypeScript 和 JavaScript ORM(对象关系映射)框架,支持多种数据库,包括 MySQL、PostgreSQL、SQLite、SQL Server 等。本文将介绍 TypeORM 的基本概念、安装、配置和常用操作。
一、安装与配置
- 安装 TypeORM 和数据库驱动
首先,安装 TypeORM 和所需的数据库驱动。以 MySQL 为例:
npm install typeorm mysql2
- 创建配置文件
在项目根目录下创建 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));
四、常用操作
- 插入数据
使用 save
方法插入或更新数据:
const user = new User();
user.name = "Jane Doe";
user.age = 30;
await connection.manager.save(user);
- 查询数据
使用 find
方法查询所有数据,findOne
方法查询单个数据:
const users = await connection.manager.find(User);
const user = await connection.manager.findOne(User, { where: { name: "Jane Doe" } });
- 更新数据
使用 save
方法更新数据:
const userToUpdate = await connection.manager.findOne(User, 1);
if (userToUpdate) {
userToUpdate.age = 35;
await connection.manager.save(userToUpdate);
}
- 删除数据
使用 remove
方法删除数据:
const userToRemove = await connection.manager.findOne(User, 1);
if (userToRemove) {
await connection.manager.remove(userToRemove);
}
五、高级功能
- 关系(Relations)
TypeORM 支持实体之间的关系,如一对一、一对多、多对多。
@Entity()
export class Profile {
@PrimaryGeneratedColumn()
id: number;
@Column()
bio: string;
@OneToOne(() => User)
@JoinColumn()
user: User;
}
- 迁移(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. findOne
和 find
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 官方文档。