- 创建项目
- Nest 控制器
- nest 配置路由请求数据
- Nest 服务
- Nest 模块
- 配置静态资源
- 配置模板引擎
- Cookie 的使用
- Session 的使用
- 跨域,前缀路径、网站安全、请求限速
- 管道、守卫、拦截器、过滤器、中间件
- 一例看懂中间件、守卫、管道、异常过滤器、拦截器
- 数据验证
- 配置抽离
- 环境配置
- 文件上传与下载
- 实现图片随机验证码
- 邮件服务
- nest 基于 possport + jwt 做登陆验证
- 对数据库的密码加密:md5 和 bcryptjs
- 角色权限
- 定时任务
- 接入 Swagger 接口文档
- nest 连接 Mongodb
- typeORM 操作 Mysql 数据库
- nest 统一处理数据库操作的查询结果
- 数据库实体设计与操作
- typeorm 增删改查操作
- typeorm 使用事务的 3 种方式
- typeorm 一对一关系设计与增删改查
- typeorm 一对多和多对一关系设计与增删改查
- typeorm 多对多关系设计与增删改查
- nest 连接 Redis
- 集成 redis 实现单点登录
- Q:nestJS 注入其他依赖时为什么还需要导入其 module
文章来源于网络收集而来,版权归原创者所有,如有侵权请及时联系!
typeorm 一对一关系设计与增删改查
实体如何设计一对一关系?如何增删改查?
一对一关系
- 定义:一对一是一种 A 只包含一个 B ,而 B 只包含一个 A 的关系
- 其实就是要设计两个表:一张是主表,一张是副表,查找主表时,关联查找副表
- 有外键的表称之为副表,不带外键的表称之为主表
- 如:一个账户对应一个用户信息,主表是账户,副表是用户信息
- 如:一个用户对应一张用户头像图片,主表是用户信息,副表是头像地址
一对一实体设计
主表:
- 使用
@OneToOne()
来建立关系 - 第一个参数:
() => AvatarEntity
, 和谁建立关系? 和AvatarEntity
建立关系 - 第二个参数:
(avatar) => avatar.user)
,和哪个字段联立关系?avatar
就是AvatarEntity
的别名,可随便写,和AvatarEntity
的userinfo
字段建立关系 - 第三个参数:
RelationOptions
关系选项
import { Column, Entity, PrimaryGeneratedColumn, OneToOne, } from 'typeorm'; import { AvatarEntity } from './avatar.entity'; @Entity({ name: 'users' }) export class UsersEntity { @PrimaryGeneratedColumn() id: number; @Column() username: string; @Column() password: string; @OneToOne(() => AvatarEntity, (avatar) => avatar.userinfo) avatar: AvatarEntity; }
副表
参数:同主表一样 主要:根据 @JoinColumn({ name: ‘user_id’ })
来分辨副表, name
是设置数据库的外键名字,如果不设置是 userId
import { Entity, PrimaryGeneratedColumn, Column, OneToOne, JoinColumn, } from 'typeorm'; import { UsersEntity } from './user.entity'; @Entity({ name: 'avatar' }) export class AvatarEntity { @PrimaryGeneratedColumn() id: number; @Column({ type: 'varchar' }) url: string; @OneToOne(() => UsersEntity, (user) => user.avatar) @JoinColumn({ name: 'userinfo_id' }) userinfo: UsersEntity; }
一对一增删改查
- 注意:只要涉及两种表操作的,就需要开启事务:同时失败或同时成功,避免数据不统一
- 在这里:创建,修改,删除都开启了事务
- 注意:所有数据应该是由前端传递过来的,这里为了方便,直接硬编码了(写死)
// user.controller.ts import { Controller, Get, Post, Body, Patch, Query, Param, Delete, HttpCode, HttpStatus, ParseIntPipe, } from '@nestjs/common'; import { Transaction, TransactionManager, EntityManager } from 'typeorm'; 开启事务第一步:引入 import { UserService } from './user.service-oto'; @Controller('user') export class UserController { constructor(private readonly userService: UserService) { } @Get() async findAll() { const [data, count] = await this.userService.findAll(); return { count, data }; } @Get(':id') async findOne(@Param('id', new ParseIntPipe()) id: number) { return await this.userService.findOne(id); } @Post(':id') @HttpCode(HttpStatus.OK) @Transaction() 开启事务第二步:装饰接口 async create( @Param('id', new ParseIntPipe()) id: number, @TransactionManager() maneger: EntityManager, 开启事务第三步:获取事务管理器 ) { return await this.userService.create(id, maneger); 开启事务第四步:传递给 service,使用数据库时调用 } @Patch(':id') @Transaction() async update( @Param('id', new ParseIntPipe()) id: number, @TransactionManager() maneger: EntityManager, ) { return await this.userService.update(id, maneger); } @Delete(':id') @Transaction() async remove( @Param('id', new ParseIntPipe()) id: number, @TransactionManager() maneger: EntityManager, ) { return await this.userService.remove(id, maneger); } }
// user.service.ts import { Injectable } from '@nestjs/common'; import { Repository, Connection, UpdateResult, EntityManager } from 'typeorm'; import { InjectRepository } from '@nestjs/typeorm'; import { UsersEntity } from './entities/user.entity'; import { AvatarEntity } from './entities/avatar.entity'; import { ToolsService } from '../../utils/tools.service'; @Injectable() export class UserService { constructor( @InjectRepository(UsersEntity) private readonly usersRepository: Repository<UsersEntity>, @InjectRepository(AvatarEntity) private readonly avatarRepository: Repository<AvatarEntity>, private connection: Connection, ) { } 一对一增删改查 查找全部 async findAll() { 使用封装好的方式 // return await this.usersRepository.findAndCount({ relations: ['avatar'] }); 使用 QueryBuilder 的方式 const list = await this.usersRepository .createQueryBuilder('UsersEntity') .leftJoinAndSelect('UsersEntity.avatar', 'AvatarEntity.userinfo') .getManyAndCount(); return list; } 根据主表 id 查找一对一 async findOne(id: number) { const result = await this.usersRepository.findOne(id, { relations: ['avatar'], }); if (!result) ToolsService.fail('用户 id 不存在'); return result; } 根据主表 id 创建一对一 async create(id: number, manager: EntityManager) { const urlObj = { url: `http://www.dmyxs.com/images/${id}.png`, }; const user = await this.usersRepository.findOne({ id }); 先查找用户 if (!user) ToolsService.fail('用户 id 不存在'); 如果没找到,抛出错误,由过滤器捕获错误 创建实体的两种方式:new 和 create,new 的方式方便条件判断 创建实体方式一: const avatarEntity = this.avatarRepository.create({ url: urlObj.url }); 创建实体 创建实体方式二: //const avatarEntity = new AvatarEntity(); //avatarEntity.url = urlObj.url; const avatarUrl = await manager.save(avatarEntity); 使用事务保存副表 user.avatar = avatarUrl; 主表和副表建立关系 await manager.save(user); 使用事务保存主表 return '新增成功'; 如果过程出错,不会保存 } 根据主表 id 更改一对一 要更改的副表 id,会从前端传递过来 async update(id: number, manager: EntityManager) { const urlObj = { id: 18, url: `http://www.dmyxs.com/images/${id}-update.jpg`, }; const user = await this.usersRepository.findOne( { id } ); 先查找用户 if (!user) ToolsService.fail('用户 id 不存在'); 如果没找到 id 抛出错误,由过滤器捕获错误 const avatarEntity = this.avatarRepository.create({ url: urlObj.url }); 创建要修改的实体 使用事务更新方法:1 参:要修改的表,2 参:要修改的 id, 3 参:要更新的数据 await manager.update(AvatarEntity, urlObj.id, avatarEntity); return '更新成功'; } 根据主表 id 删除一对一 async remove(id: number, manager: EntityManager): Promise<any> { const user = await this.usersRepository.findOne(id); if (!user) ToolsService.fail('用户 id 不存在'); 只删副表的关联数据 await manager.delete(AvatarEntity, { user: id }); 如果连主表用户一起删,加下面这行代码 //await manager.delete(UsersEntity, id); return '删除成功'; } }
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论