快速学习和上手一个框架或者一个技能,将会成为日后混饭吃的本领。对于快速上手一个新的东西或是碰到问题如何快速解决,我曾经一度不知道该如何去做。在职场混了几年后,我好像慢慢找到了一些方法。
看文档,跑最小demo,跑代码看看,点进方法里面去看看里面如何实现,入参返回值等等,完了之后不断总结,这就是一个很不错的学习新东西的技巧。动手动脑子多调试多谷歌,就没啥问题了。
那么如何快速定位问题呢?看重要程度,重要紧急的话,先代码回滚,然后找复现路径和规律,再去排查。
概念解析
守卫只有一个职责。他们决定了请求是否要被路由处理程序处理,取决于运行时某些情况(例如权限,角色,ACL访问控制列表)。这些通常被称作授权
每个守卫必须实现一个canActivate()函数。此函数应该返回一个布尔值,指示是否允许当前请求
中间件和守卫(授权)的差别:守卫有执行上下文,可以很明确的知道接下来要执行什么。中间件只有next() 守卫的执行时期:在所有的中间件之后,在管道之前执行
守卫在每个中间件之后执行,但在任何拦截器或管道之前执行。
请求生命周期
收到请求
全局绑定的中间件
模板绑定的中间件
全局守卫
控制层守卫
路由守卫
全局拦截器/控制层拦截器/路由拦截器
全局管道/控制器管道/路由管道/路由参数
异常过来器/服务器响应
queryRunner查询事物,提供单一数据库连接
QueryBuilder优雅的使用查询语句,就是语法糖
EntityManager是所有实体的集合,查找的方式也不一样,多一个.manager
Repository就是单独的一个实体
import { SetMetadata } from “@nestjs/common”;@SetMetadata() 来将自定义元数据附加在路由处理程序上的能力。元数据提供了我们缺少的一个智能的守卫来做决定需要的角色信息,设置这个这个角色的信息
InjectRepository 是一种依赖注入的技术,用于在程序中自动注入数据库操作的 Repository 实例。 常用在Repository查询语句中
Injectable: Nest.js 框架中的一个装饰器(Decorator),用于将一个类定义为可被依赖注入的类。创建一个 Nest.js 服务类时,我们需要将这个类定义为 Injectable 类型,这样它才能被 Nest.js 容器管理。在 class 前面添加 @Injectable() 装饰器就可以将这个类定义为 Injectable 类型
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm'; // 操作数据库
import { Repository } from 'typeorm'; // 操作数据表
import { UserEntity } from 'src/common/entity/user.entity';
@Injectable()
export class UserService {
constructor(
@InjectRepository(UserEntity) // 注入用户表(用户实例 用于进行数据库的操作
private readonly userRepository: Repository<UserEntity>,//表示用户实体的操作类,usersRepository 是自定义的变量名,表示一个 User 实体的 Repository 对象的引用
) {}
async findAll() {
return await this.userRepository.find();
}
}
如果在 createQueryBuilder() 查询语句的链式调用中没有跟着 .getOne() 或者 .getMany() 等方法,将无法获得具体的查询结果,而只会返回一个 TypeORM 的 QueryBuilder 实例。
这个实例可以在后续的调用中继续构建查询,加入更多的查询条件、排序规则等等,在最后通过 .getOne() 或 .getMany() 等方法获取查询结果
EntityManager和DataSource 的区别
其实从名字就能看出一些大概来 EntityManager是TypeORM提供的高级API,用于应用程序的数据操纵,而DataSource是用于与数据库建立连接的基础设施组件。(表操作和库操作
DataSource是连接到数据库的核心部分,用于建立与数据库之间的连接,执行查询和获取结果
EntityManager则是用于在应用程序中创建、读取、更新和删除数据的API
DataSource负责处理连接池和连接的创建、释放和管理等基础任务。因此,在大多数情况下,您不需要与DataSource直接交互,而是让TypeORM自动为您处理。
EntityManager则提供面向对象的API,可以让开发者更加方便地进行数据操作。你可以通过它进行各种数据库操作,例如插入、更新、删除和查询等
getManager 和 getConnection 的区别
getManager 用于实体操作,而 getConnection 用于访问更底层的数据库连接和 SQL 操作。可以根据具体的场景来选择使用哪一个方法,或者同时使用它们来实现更复杂的操作。是不是和上面的很相似
getManager 方法返回一个 EntityManager 实例,用于执行实体操作(例如读取、保存等)。EntityManager控制与实体相关的上下文以及实体状态管理,可以使用它来执行数据库操作。
getConnection 方法用于返回连接数据库的底层技术实现。Connection 对象提供了这些数据库连接,可以用它来执行原始 SQL 查询和事务控制等操作。如果想要进行一些特殊的查询操作,或是想要使用原生 SQL 查询来操作数据库,就需要使用 getConnection 获取 Connection 对象操作。
创建事务的两种方式
createQueryRunner创建一个事务,数据库事务代表在数据库管理系统(DBMS)中针对数据库的一组操作,这组操作是有关的、可靠的并且和其他事务相互独立的
使用 EntityManager 的 transaction 方法,如果回调函数中的任何操作抛出异常,则执行自动回滚操作并抛出此异常。如果回调函数成功完成,则事务将被提交
我们使用 EntityManager 对象来执行数据库操作,并使用 queryRunner 属性来手动启动、提交和回滚事务。使用 EntityManager 和 queryRunner 可以更好地控制事务的行为,同时保留了 TypeORM 的高级特性
手动启动、提交和回滚事务
import { getManager } from 'typeorm';
const updateSalaries = async (employees, bonuses) => {
const entityManager = getManager(); // 它返回一个 EntityManager 对象,从而允许你在你的应用程序的不同位置执行实体操作
const queryRunner = entityManager.queryRunner;
// 启动事务
await queryRunner.startTransaction();
try {
// 在事务中更新每个雇员的薪水和奖金
for (let i = 0; i < employees.length; i++) {
const employee = employees[i];
const bonus = bonuses[i];
employee.salary += bonus;
employee.bonus = bonus;
await entityManager.save(employee);
}
// 提交事务
await queryRunner.commitTransaction();
} catch (err) {
// 回滚事务
await queryRunner.rollbackTransaction();
console.error(err);
} finally {
// 清理使用的资源
await queryRunner.release();
}
}
where 查询语句的几种实用方式
等值查询:createQueryBuilder(‘user’) .where(‘user.username = :username’, {username: ‘johndoe’});
in 查询:createQueryBuilder(‘user’) .where(‘user.id IN (:…ids)’, { ids: [1, 2, 3] });
not in 查询:createQueryBuilder(‘user’) .where(‘user.id NOT IN (:…ids)’, { ids: [1, 2, 3] });
like 查询:createQueryBuilder(‘user’) .where(‘user.username LIKE :username’, { username: ‘%johndoe%’ });
not like 查询:createQueryBuilder(‘user’) .where(‘user.username NOT LIKE :username’, { username: ‘%johndoe%’ });
between 查询:createQueryBuilder(‘user’) .where(‘user.registeredAt BETWEEN :startDate AND :endDate’, { startDate: ‘2021-01-01’, endDate: ‘2021-12-31’ });
or 查询:createQueryBuilder(‘user’) .where(‘user.username LIKE :username’) .orWhere(‘user.age = :age’) .setParameters({ username: ‘%johndoe%’, age: 30 });
and 查询:createQueryBuilder(‘user’) .where(‘user.username LIKE :username’) .andWhere(‘user.age = :age’) .setParameters({ username: ‘%johndoe%’, age: 30 });
is null 查询:createQueryBuilder(‘user’) .where(‘user.username IS NULL’);
where里面直接设置参数和使用setParameters有啥区别
一是直接将参数写在查询语句中,二是使用 setParameters 方法。这两种方式的区别在于可读性和安全性。使用 setParameters 方法可以想 SQL prepared 语句一样定义参数,这样不仅可以避免 SQL 注入的风险,而且也使查询语句更易于理解和维
Gitalking ...