TypeORM 浅析
TypeORM 是一款基于 TypeScript 或 JavaScript 的 ORM(对象关系映射)工具,允许开发者通过面向对象的方式与数据库交互。它支持多个数据库类型,包括 PostgreSQL、MySQL、SQLite 等。TypeORM 提供了强大的实体映射、关系管理以及数据库迁移等功能,使数据库操作更加高效和简洁。
1. 安装与配置
1.1. 配置 tsconfig
{"compilerOptions": {"types": ["node"],"target": "ESNext","module": "ESNext","strict": true,"esModuleInterop": true,"moduleResolution": "Node","skipLibCheck": true,"outDir": "./dist","rootDir": "./src","strictPropertyInitialization": false,"sourceMap": false,/*** 对于注解配置*/"experimentalDecorators": true,"emitDecoratorMetadata": true},"include": ["src/**/*.ts"],"exclude": ["node_modules", "dist"]
}
1.2. 安装 TypeORM 和相关依赖
npm install typeorm reflect-metadata pg
typeorm:TypeORM 的核心库。
reflect-metadata:用于 TypeScript 中的装饰器支持。
pg:PostgreSQL 驱动。
1.3. 配置与初始化 DataSource
以下是使用 TypeORM 初始化 PostgreSQL 数据源的代码示例:
import "reflect-metadata";
import { Photo } from "./entities/Photo";
import { DataSource, DataSourceOptions } from "typeorm";const dataSourceConfig: DataSourceOptions = {type: "postgres",host: "127.0.0.1",port: 5432,username: "postgres",password: "123456",database: "test",synchronize: true,logging: false,entities: [Photo],
};const appDataSource = new DataSource(dataSourceConfig);
type:指定数据库类型。
entities:指定项目中的实体类。
synchronize:是否自动同步数据库结构,生产环境建议关闭。
2. 核心概念与使用
2.1. 实体
实体类与数据库表进行映射,定义表的结构和字段。通过装饰器,我们可以定义主键、列以及各种关系。
示例:创建 Photo 实体。
import { Entity, PrimaryGeneratedColumn, Column } from "typeorm";@Entity()
export class Photo {@PrimaryGeneratedColumn()id: number;@Column()name: string;@Column()description: string;@Column()filename: string;@Column()views: number;@Column()isPublished: boolean;
}
@Entity():标记类为实体,映射为数据库表。
@PrimaryGeneratedColumn():主键列,值自动生成。
@Column():表示该字段映射为数据库列。
2.2. 使用 Repository 进行数据操作
TypeORM 通过 Repository 提供了一系列数据操作的方法,如 find、save、update、delete 等,简化了 CRUD 操作。
示例:插入数据并查询。
import { Photo } from "./entity/Photo";// 插入新的照片数据
const photo = new Photo();
photo.name = "My First Photo";
photo.description = "This is the description";
photo.filename = "photo.jpg";
photo.views = 0;
photo.isPublished = true;AppDataSource.getRepository(Photo).save(photo).then(savedPhoto => {console.log("Photo has been saved:", savedPhoto);}).catch(error => console.log("Error:", error));// 查询所有照片数据
AppDataSource.getRepository(Photo).find().then(photos => {console.log("All photos:", photos);}).catch(error => console.log("Error:", error));
save():保存新数据或更新现有数据。
find():查询表中所有记录。
或者通过 manager 进行管理。
const test = async () => {await appDataSource.initialize();// 插入数据const photo = new Photo();photo.name = "xiaoming";photo.description = "I am xiaoming";photo.status = true;await appDataSource.manager.save(photo);// 或者使用 SQLconst photoRes = await appDataSource.manager.query("SELECT * FROM photo");console.log(photoRes);
};test();
2.3. 条件查询与分页
通过 find 方法可以实现条件查询、分页和排序。
示例:按条件查询照片。
AppDataSource.getRepository(Photo).find({where: { isPublished: true },take: 10, // 限制返回的记录数skip: 5, // 跳过前 5 条记录order: { views: "DESC" } // 按照 views 字段降序排序
}).then(photos => {console.log("Published photos:", photos);
});
3. 关系映射
TypeORM 支持各种关系映射,包括一对一、一对多、多对多。在多个表之间建立关系时,TypeORM 提供了相应的装饰器,如 @OneToMany、@ManyToOne 等。
3.1. 一对多关系
在关系映射中,User 和 Photo 之间存在一对多的关系,即一个用户可以拥有多张照片。
示例:用户与照片的一对多关系。
import { Entity, PrimaryGeneratedColumn, Column, OneToMany, ManyToOne } from "typeorm";
import { Photo } from "./Photo";@Entity()
export class User {@PrimaryGeneratedColumn()id: number;@Column()name: string;@OneToMany(() => Photo, photo => photo.user)photos: Photo[];
}@Entity()
export class Photo {@PrimaryGeneratedColumn()id: number;@Column()name: string;@ManyToOne(() => User, user => user.photos)user: User;
}
@OneToMany():表示一个用户可以拥有多张照片。
@ManyToOne():表示每张照片属于一个用户。
4. TypeORM 的高级特性
TypeORM 提供了一些高级特性,帮助你处理复杂的数据库操作,例如事务、软删除和乐观锁。
4.1. 乐观锁
乐观锁用于确保并发操作的安全性,防止多个事务同时修改同一条记录。
示例:使用乐观锁更新记录。
const photo = await AppDataSource.getRepository(Photo).findOneBy({ id: 1 });
photo.views += 1;
await AppDataSource.getRepository(Photo).save(photo, { lock: { mode: "optimistic", version: photo.version + 1 || 1 }
});
4.2. 事务
事务用于保证一组数据库操作的原子性,确保操作要么全部执行,要么全部回滚。
示例:在事务中执行多次数据库操作。
await AppDataSource.transaction(async transactionalEntityManager => {await transactionalEntityManager.save(new Photo());await transactionalEntityManager.save(new User());
});