关系模型定义

多对一/一对多 **
@ManyToOne 和 @OneToMany 成对出现,例如一个实体拥有多条日志,而多条日志属于一个实体。 第一个参数返回对应的表的目标实体,第二个参数指定对应表的对应字段名。由于指定了对应实体,这里可以推导出类型。 注解内容:user:
ts
@Entity()
export class User {
@PrimaryGeneratedColumn()
id: number;
@Column()
username: string;
@Column()
password: string;
// OneToMany 定义:一个用户对应多个日志记录
@OneToMany(() => Logs, (logs) => logs.user)
logs: Logs[]; // 一个用户拥有多个日志数据,在数据库中被解释为外键
}logs:
ts
// logs.entity.ts
import { Entity, PrimaryGeneratedColumn, Column, ManyToOne } from 'typeorm';
import { User } from './user.entity';
@Entity()
export class Logs {
@PrimaryGeneratedColumn()
id: number;
@Column()
path: string;
@Column()
method: string;
@Column()
data: string;
@ManyToOne(() => User, (user) => user.logs)
@JoinColumn({name:'userwaijian'}) // 也可指定外键列名,默认为 userId
user: User; // 每个日志被唯一的用户拥有,通过外键引用
}多对多
对应 user 和 user_roles
ts
@ManyToMany(() => User, (user) => user.roles)
users: User[];
@ManyToMany(() => Role, (role) => role.users)
@JoinTable() // 使用 JoinTable 来创建联接表
roles: Role[];从已有数据库生成 typeORM 实体类
https://www.npmjs.com/package/typeorm-model-generator
CRUD 操作
简单操作可以写在 controller 层,复杂操作则在 service 层。
依赖注入 (DI) 容器
将对象的创建和依赖关系的管理交给外部容器管理,而非直接手动实例化对象。通过构造函数、属性或方法注入依赖。 注册提供者(Provider) 可以被注入的类需要注册为提供者 provider,由 @Injectable() 标记,并且在模块的 providers 数组中注册。 注入依赖 主要通过构造函数注入。
ts
constructor(private readonly userService: UserService) {}

步骤
- 数据访问层:在根模块上导入 typeORM
ts
@Module({
imports: [
TypeOrmModule.forRootAsync({
imports: [ConfigModule],
inject: [ConfigService],
useFactory: (configService: ConfigService) => {
console.log("config:", configService);
console.log('开始配置数据库连接');
const dbConfig = {
type: configService.get('TYPEORM_TYPE'),
host: configService.get('TYPEORM_HOST'),
port: configService.get('TYPEORM_PORT'),
username: configService.get('TYPEORM_USERNAME'),
password: configService.get('TYPEORM_PASSWORD'),
database: configService.get('TYPEORM_DATABASE'),
synchronize: true,
entities: [User,Profile,Logs,Roles], // 实体类数组
logging: ['error'],
} as TypeOrmModuleOptions;
console.log('数据库配置完成:', dbConfig);
return dbConfig;
},
}),
],
controllers: [],
providers: [],
})- 设置实体类
entity - 业务逻辑层:CRUD 方法
ts
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { User } from './user.entity';
import { Repository } from 'typeorm';
// 逻辑层
@Injectable()
export class UserService {
constructor(
@InjectRepository(User) private readonly userRepository: Repository<User>,
) {} // 注入 User 实体对应的 Repository
async getAll() {
const res = await this.userRepository.find({});
console.log('database res:', res);
return res;
}
async findOne(username: string) {
const res = await this.userRepository.findOne({ where: { username } });
return res;
}
async create(user: User) {
const user_temp = await this.userRepository.create(user); // user属性key与对应的user表一致
return this.userRepository.save(user_temp);
}
// 根据传入的字段创建一个实体对象。这个对象是一个临时的 JavaScript 实例,用于表示数据库中的一行数据。然后再用save
// 做持久化
async update(id: number, user: Partial<User>) {
await this.userRepository.update(id, user);
}
async remove(id: number) {
await this.userRepository.delete(id);
}
}- 路由层:
ts
Controller('user')
export class UserController {
constructor(
private userService: UserService,
private configService: ConfigService,
) {}
@Get('getuser')
getUsers() {
return this.userService.getAll();
}
@Post('adduser')
addUser(){
const user = {
username: 'test2',
password: 'test'
} as User;
return this.userService.create(user);
}
}ORM 操作外键反向关系
先从返向关系对应的表里 find 出对应的记录,成为一个 ORM 对象,再去操作这个 ORM 对象:
ts
@Post('addlog')
async addLog() {
const users: User[] = [await this.userService.getUserById(1) as User, await this.userService.getUserById(2) as User];
let logs: Logs[] = [{
id: 1,
path: '/api/v1/user',
method: 'GET',
data: '',
result: 200,
userId: users[0]
}];
return this.userService.addLog(logs[0]);
}