Nestjs项目实战 集成TypeORM实现数据库操作
在NestJS项目中集成TypeORM时遇到几个问题想请教:
-
如何正确配置TypeORM模块连接数据库?我的
ormconfig.json
总是报错,有没有推荐的最佳实践? -
实体类(Entity)与数据库表字段的映射关系该如何定义?比如主键、外键、枚举类型的处理。
-
在Service中调用TypeORM的Repository时,是直接注入Repository好,还是通过自定义Provider封装更好?
-
遇到复杂查询(如联表、分页)时,用QueryBuilder和原生SQL哪种方式更合适?
-
有没有优雅处理事务的方法?目前用
EntityManager
感觉代码比较冗余。
项目用的是MySQL,NestJS版本是v9。
在NestJS项目中集成TypeORM实现数据库操作的步骤如下:
-
安装依赖:使用npm或yarn安装必要的包:
npm install [@nestjs](/user/nestjs)/typeorm typeorm mysql2
这里以MySQL为例,如果用其他数据库,需安装对应的驱动。
-
配置TypeORM模块:在
app.module.ts
中引入并配置TypeORM:import { Module } from '[@nestjs](/user/nestjs)/common'; import { TypeOrmModule } from '[@nestjs](/user/nestjs)/typeorm'; [@Module](/user/Module)({ imports: [ TypeOrmModule.forRoot({ type: 'mysql', host: 'localhost', port: 3306, username: 'root', password: '', database: 'test_db', entities: [__dirname + '/**/*.entity{.ts,.js}'], synchronize: true, // 开发环境建议开启 }), ], }) export class AppModule {}
-
创建实体类:通过TypeORM定义数据表结构,例如
user.entity.ts
:import { Entity, PrimaryGeneratedColumn, Column } from 'typeorm'; [@Entity](/user/Entity)() export class User { @PrimaryGeneratedColumn() id: number; @Column() name: string; @Column() email: string; }
-
编写服务层:利用注入的
EntityManager
进行增删改查操作。例如:import { Injectable } from '[@nestjs](/user/nestjs)/common'; import { InjectRepository } from '[@nestjs](/user/nestjs)/typeorm'; import { Repository } from 'typeorm'; import { User } from './user.entity'; [@Injectable](/user/Injectable)() export class UserService { constructor( @InjectRepository(User) private usersRepository: Repository<User>, ) {} async createUser(name: string, email: string): Promise<User> { const user = new User(); user.name = name; user.email = email; return await this.usersRepository.save(user); } }
-
路由与控制器绑定:在Controller中调用Service完成CRUD逻辑。
遵循以上步骤即可完成基本的数据库操作集成。
在NestJS项目中集成TypeORM进行数据库操作非常简单。首先,在package.json
中安装必要的依赖:
npm install @nestjs/typeorm typeorm mysql2 --save
然后,在app.module.ts
中配置TypeORM模块:
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_db',
entities: [__dirname + '/**/*.entity{.ts,.js}'],
synchronize: true, // 生产环境建议关闭
}),
],
})
export class AppModule {}
接着定义实体类,比如创建一个User实体:
import { Entity, PrimaryGeneratedColumn, Column } from 'typeorm';
@Entity()
export class User {
@PrimaryGeneratedColumn()
id: number;
@Column()
name: string;
@Column()
age: number;
}
最后,在服务中注入Repository来操作数据库:
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { User } from './user.entity';
@Injectable()
export class UserService {
constructor(
@InjectRepository(User)
private usersRepository: Repository<User>,
) {}
findAll(): Promise<User[]> {
return this.usersRepository.find();
}
findOne(id: number): Promise<User> {
return this.usersRepository.findOneBy({ id });
}
async create(user: Partial<User>): Promise<User> {
const newUser = this.usersRepository.create(user);
return this.usersRepository.save(newUser);
}
async update(id: number, user: Partial<User>): Promise<void> {
await this.usersRepository.update(id, user);
}
async remove(id: number): Promise<void> {
await this.usersRepository.delete(id);
}
}
这样就完成了基本的数据库操作功能。
NestJS 集成 TypeORM 实现数据库操作
TypeORM 是 Node.js 中最流行的 ORM 之一,与 NestJS 集成良好。下面是实战步骤:
1. 安装必要依赖
npm install @nestjs/typeorm typeorm mysql2 # 根据数据库选择相应驱动
2. 配置数据库连接
在 app.module.ts
中配置:
import { TypeOrmModule } from '@nestjs/typeorm';
@Module({
imports: [
TypeOrmModule.forRoot({
type: 'mysql', // 数据库类型
host: 'localhost',
port: 3306,
username: 'root',
password: 'password',
database: 'test',
entities: [__dirname + '/**/*.entity{.ts,.js}'],
synchronize: true, // 自动同步数据库结构,生产环境建议关闭
}),
// ...其他模块
],
})
export class AppModule {}
3. 创建实体(Entity)
// user.entity.ts
import { Entity, PrimaryGeneratedColumn, Column } from 'typeorm';
@Entity()
export class User {
@PrimaryGeneratedColumn()
id: number;
@Column()
name: string;
@Column()
email: string;
}
4. 创建服务层
// users.service.ts
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { User } from './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> {
return this.usersRepository.findOne({ where: { id } });
}
create(user: User): Promise<User> {
return this.usersRepository.save(user);
}
async update(id: number, user: Partial<User>): Promise<User> {
await this.usersRepository.update(id, user);
return this.usersRepository.findOne({ where: { id } });
}
async remove(id: number): Promise<void> {
await this.usersRepository.delete(id);
}
}
5. 创建控制器
// users.controller.ts
import { Controller, Get, Post, Body, Param, Put, Delete } from '@nestjs/common';
import { UsersService } from './users.service';
import { User } from './user.entity';
@Controller('users')
export class UsersController {
constructor(private readonly usersService: UsersService) {}
@Get()
findAll() {
return this.usersService.findAll();
}
@Get(':id')
findOne(@Param('id') id: string) {
return this.usersService.findOne(+id);
}
@Post()
create(@Body() user: User) {
return this.usersService.create(user);
}
@Put(':id')
update(@Param('id') id: string, @Body() user: Partial<User>) {
return this.usersService.update(+id, user);
}
@Delete(':id')
remove(@Param('id') id: string) {
return this.usersService.remove(+id);
}
}
6. 注册模块
// users.module.ts
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { UsersService } from './users.service';
import { UsersController } from './users.controller';
import { User } from './user.entity';
@Module({
imports: [TypeOrmModule.forFeature([User])],
providers: [UsersService],
controllers: [UsersController],
})
export class UsersModule {}
高级特性
- 关系:可以使用
@OneToMany
、@ManyToOne
等装饰器定义关系 - 事务:使用
@Transaction
和@TransactionManager
装饰器 - 查询构建器:通过
repository.createQueryBuilder()
构建复杂查询 - 分页:使用
skip
和take
参数
生产环境中,建议关闭 synchronize
选项,使用迁移来管理数据库结构变更。