NestJS TypeORM集成 #
TypeORM简介 #
TypeORM是一个支持TypeScript的ORM框架,可以运行在Node.js、浏览器、Cordova、PhoneGap等平台上。它支持多种数据库,包括MySQL、PostgreSQL、MariaDB、SQLite、MS SQL Server等。
安装依赖 #
bash
npm install @nestjs/typeorm typeorm mysql2
# 或 PostgreSQL
npm install @nestjs/typeorm typeorm pg
# 或 SQLite
npm install @nestjs/typeorm typeorm better-sqlite3
配置TypeORM #
使用forRoot配置 #
typescript
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
@Module({
imports: [
TypeOrmModule.forRoot({
type: 'mysql',
host: 'localhost',
port: 3306,
username: 'root',
password: 'password',
database: 'test',
entities: [],
synchronize: true,
}),
],
})
export class AppModule {}
使用环境变量 #
typescript
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { ConfigModule, ConfigService } from '@nestjs/config';
@Module({
imports: [
ConfigModule.forRoot(),
TypeOrmModule.forRootAsync({
imports: [ConfigModule],
useFactory: (configService: ConfigService) => ({
type: 'mysql',
host: configService.get('DB_HOST'),
port: configService.get('DB_PORT'),
username: configService.get('DB_USERNAME'),
password: configService.get('DB_PASSWORD'),
database: configService.get('DB_DATABASE'),
entities: [__dirname + '/**/*.entity{.ts,.js}'],
synchronize: configService.get('NODE_ENV') !== 'production',
}),
inject: [ConfigService],
}),
],
})
export class AppModule {}
配置选项 #
| 选项 | 说明 |
|---|---|
type |
数据库类型 |
host |
数据库主机 |
port |
数据库端口 |
username |
用户名 |
password |
密码 |
database |
数据库名 |
entities |
实体类 |
synchronize |
自动同步表结构 |
logging |
日志级别 |
定义实体 #
基本实体 #
typescript
import { Entity, Column, PrimaryGeneratedColumn } from 'typeorm';
@Entity('users')
export class User {
@PrimaryGeneratedColumn()
id: number;
@Column()
name: string;
@Column({ unique: true })
email: string;
@Column({ select: false })
password: string;
@Column({ default: true })
isActive: boolean;
@Column({ type: 'text', nullable: true })
bio: string;
@Column({ type: 'datetime', default: () => 'CURRENT_TIMESTAMP' })
createdAt: Date;
@Column({ type: 'datetime', nullable: true })
updatedAt: Date;
}
列装饰器 #
| 装饰器 | 说明 |
|---|---|
@PrimaryGeneratedColumn() |
自增主键 |
@PrimaryColumn() |
自定义主键 |
@Column() |
普通列 |
@CreateDateColumn() |
创建时间 |
@UpdateDateColumn() |
更新时间 |
@DeleteDateColumn() |
软删除时间 |
@VersionColumn() |
版本号 |
列选项 #
typescript
@Column({
type: 'varchar',
length: 100,
nullable: false,
unique: true,
default: 'default value',
select: false,
comment: '用户邮箱',
})
email: string;
实体关系 #
一对一关系 #
typescript
import { Entity, PrimaryGeneratedColumn, Column, OneToOne, JoinColumn } from 'typeorm';
@Entity()
export class User {
@PrimaryGeneratedColumn()
id: number;
@Column()
name: string;
@OneToOne(() => Profile, profile => profile.user)
@JoinColumn()
profile: Profile;
}
@Entity()
export class Profile {
@PrimaryGeneratedColumn()
id: number;
@Column()
avatar: string;
@OneToOne(() => User, user => user.profile)
user: User;
}
一对多关系 #
typescript
import { Entity, PrimaryGeneratedColumn, Column, OneToMany, ManyToOne } from 'typeorm';
@Entity()
export class User {
@PrimaryGeneratedColumn()
id: number;
@Column()
name: string;
@OneToMany(() => Post, post => post.author)
posts: Post[];
}
@Entity()
export class Post {
@PrimaryGeneratedColumn()
id: number;
@Column()
title: string;
@ManyToOne(() => User, user => user.posts)
author: User;
}
多对多关系 #
typescript
import { Entity, PrimaryGeneratedColumn, Column, ManyToMany, JoinTable } from 'typeorm';
@Entity()
export class User {
@PrimaryGeneratedColumn()
id: number;
@ManyToMany(() => Role, role => role.users)
@JoinTable()
roles: Role[];
}
@Entity()
export class Role {
@PrimaryGeneratedColumn()
id: number;
@Column()
name: string;
@ManyToMany(() => User, user => user.roles)
users: User[];
}
仓库模式 #
注册实体 #
typescript
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { User } from './entities/user.entity';
import { UsersService } from './users.service';
import { UsersController } from './users.controller';
@Module({
imports: [TypeOrmModule.forFeature([User])],
controllers: [UsersController],
providers: [UsersService],
})
export class UsersModule {}
使用Repository #
typescript
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { User } from './entities/user.entity';
@Injectable()
export class UsersService {
constructor(
@InjectRepository(User)
private usersRepository: Repository<User>,
) {}
findAll(): Promise<User[]> {
return this.usersRepository.find();
}
findOne(id: number): Promise<User | null> {
return this.usersRepository.findOne({ where: { id } });
}
findByEmail(email: string): Promise<User | null> {
return this.usersRepository.findOne({ where: { email } });
}
async create(userData: Partial<User>): Promise<User> {
const user = this.usersRepository.create(userData);
return this.usersRepository.save(user);
}
async update(id: number, userData: Partial<User>): Promise<User | null> {
await this.usersRepository.update(id, userData);
return this.findOne(id);
}
async remove(id: number): Promise<void> {
await this.usersRepository.delete(id);
}
}
查询构建器 #
基本查询 #
typescript
const users = await this.usersRepository
.createQueryBuilder('user')
.where('user.isActive = :isActive', { isActive: true })
.orderBy('user.createdAt', 'DESC')
.getMany();
关联查询 #
typescript
const user = await this.usersRepository
.createQueryBuilder('user')
.leftJoinAndSelect('user.posts', 'post')
.leftJoinAndSelect('post.comments', 'comment')
.where('user.id = :id', { id: 1 })
.getOne();
分页查询 #
typescript
async findWithPagination(page: number, limit: number) {
const [data, total] = await this.usersRepository
.createQueryBuilder('user')
.skip((page - 1) * limit)
.take(limit)
.getManyAndCount();
return {
data,
total,
page,
limit,
totalPages: Math.ceil(total / limit),
};
}
复杂查询 #
typescript
const users = await this.usersRepository
.createQueryBuilder('user')
.select(['user.id', 'user.name', 'user.email'])
.where('user.isActive = :isActive', { isActive: true })
.andWhere(
new Brackets(qb => {
qb.where('user.name LIKE :name', { name: '%John%' })
.orWhere('user.email LIKE :email', { email: '%@example.com%' });
}),
)
.orderBy('user.createdAt', 'DESC')
.getMany();
事务处理 #
使用@Transaction装饰器(已弃用) #
使用DataSource #
typescript
import { Injectable } from '@nestjs/common';
import { DataSource } from 'typeorm';
import { User } from './entities/user.entity';
@Injectable()
export class UsersService {
constructor(private dataSource: DataSource) {}
async createWithTransaction(userData: any) {
const queryRunner = this.dataSource.createQueryRunner();
await queryRunner.connect();
await queryRunner.startTransaction();
try {
const user = queryRunner.manager.create(User, userData);
await queryRunner.manager.save(user);
// 其他操作...
await queryRunner.commitTransaction();
return user;
} catch (error) {
await queryRunner.rollbackTransaction();
throw error;
} finally {
await queryRunner.release();
}
}
}
使用EntityManager.transaction #
typescript
await this.dataSource.transaction(async manager => {
const user = manager.create(User, userData);
await manager.save(user);
const profile = manager.create(Profile, profileData);
await manager.save(profile);
});
数据库迁移 #
创建迁移文件 #
bash
npm run typeorm migration:create -- -n CreateUserTable
迁移文件示例 #
typescript
import { MigrationInterface, QueryRunner, Table } from 'typeorm';
export class CreateUserTable1700000000000 implements MigrationInterface {
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.createTable(
new Table({
name: 'users',
columns: [
{
name: 'id',
type: 'int',
isPrimary: true,
isGenerated: true,
generationStrategy: 'increment',
},
{
name: 'name',
type: 'varchar',
length: '100',
},
{
name: 'email',
type: 'varchar',
length: '100',
isUnique: true,
},
{
name: 'createdAt',
type: 'datetime',
default: 'CURRENT_TIMESTAMP',
},
],
}),
);
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.dropTable('users');
}
}
运行迁移 #
bash
npm run typeorm migration:run
npm run typeorm migration:revert
自定义仓库 #
typescript
import { EntityRepository, Repository } from 'typeorm';
import { User } from './entities/user.entity';
@EntityRepository(User)
export class UsersRepository extends Repository<User> {
findActiveUsers(): Promise<User[]> {
return this.createQueryBuilder('user')
.where('user.isActive = :isActive', { isActive: true })
.getMany();
}
findByRole(role: string): Promise<User[]> {
return this.createQueryBuilder('user')
.innerJoin('user.roles', 'role')
.where('role.name = :role', { role })
.getMany();
}
}
总结 #
本章学习了NestJS与TypeORM的集成:
- TypeORM配置
- 实体定义
- 实体关系
- 仓库模式
- 查询构建器
- 事务处理
- 数据库迁移
接下来,让我们学习 Prisma集成。
最后更新:2026-03-28