Skip to content

241. 综合实战:开放世界(四十二)

Published:

上节创建了 database:

image.png

这节在代码里连上

安装下 TypeORM 和 mysql 驱动包:

pnpm install --save @nestjs/typeorm typeorm mysql2

在 AppModule 引入:

image.png

TypeOrmModule.forRoot({
  type: 'mysql',
  host: 'localhost',
  port: 3306,
  username: 'root',
  password: 'admin',
  database: 'open-world',
  connectorPackage: 'mysql2',
  synchronize: true,
  logging: true,
  entities: [User]
}),

创建对应的 User 类:

src/entities/user.entity.ts

指定数据库连接信息、database

然后创建一个 users 模块:

nest g resourse users --no-spec

—no-spec 是不生成测试代码。

ORM 就是把 class 和数据库表对应。

我们改一下 src/users/entities/user.entity.ts

import { Column, CreateDateColumn, Entity, PrimaryGeneratedColumn, UpdateDateColumn } from "typeorm";

@Entity()
export class User {
    @PrimaryGeneratedColumn()
    id: number;

    @Column({
        length: 50,
        unique: true
    })
    username: string;

    @Column({
        length: 255,
    })
    password: string;

    @CreateDateColumn({
        type: 'timestamp'
    })
    createdAt: Date;

    @UpdateDateColumn({
        type: 'timestamp'
    })
    updatedAt: Date;
}

通过 @Entity 标识这个 class 是 entity,然后添加 id、username、password、createdAt、updatedAt 字段

image.png

引入 User,把开发服务跑起来:

npm run start:dev

image.png

会自动创建表。

image.png

image.png

现在还没有数据,我们实现下注册的后端接口。

加一个用户模块:

nest g res user --no-spec

image.png

改下 UserService:

import { ConflictException, Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import * as bcrypt from 'bcrypt';
import { RegisterUserDto } from './dto/register-user.dto';
import { User } from './entities/user.entity';

@Injectable()
export class UserService {
  constructor(
    @InjectRepository(User)
    private readonly userRepository: Repository<User>,
  ) {}

  async register(dto: RegisterUserDto) {
    const existing = await this.userRepository.findOne({
      where: { username: dto.username },
    });
    if (existing) {
      throw new ConflictException('用户名已被占用');
    }
    const passwordHash = await bcrypt.hash(dto.password, 10);
    const user = this.userRepository.create({
      username: dto.username,
      password: passwordHash,
    });
    await this.userRepository.save(user);
    return {
      id: user.id,
      username: user.username,
      createdAt: user.createdAt,
    };
  }
}

注册逻辑就是查找用户名,如果没有被注册就保存。

在 UserController 里添加路由:

import { Body, Controller, Post } from '@nestjs/common';
import { UserService } from './user.service';
import { RegisterUserDto } from './dto/register-user.dto';

@Controller('user')
export class UserController {
  constructor(private readonly userService: UserService) {}

  @Post('register')
  register(@Body() registerUserDto: RegisterUserDto) {
    return this.userService.register(registerUserDto);
  }
}

改下 UserModule,注入 TypeOrm 的 Entity 做 user 的增删改查:

import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { UserService } from './user.service';
import { UserController } from './user.controller';
import { User } from './entities/user.entity';

@Module({
  imports: [TypeOrmModule.forFeature([User])],
  controllers: [UserController],
  providers: [UserService],
})
export class UserModule {}

跑下试试:

curl -s -X POST http://localhost:3000/user/register \
  -H "Content-Type: application/json" \
  -d '{"username":"alice","password":"password12"}'

image.png

注册成功!

总结

这节我们实现了数据库增删改查,然后实现了注册功能。

下节在 3D 场景里集成下注册。

评论