记录使用nest.js搭建个人博客的一些学习分享,通过使用和笔记希望可以让自己学的更扎实,对知识点的掌握更熟练。上次已经连接好了数据库,今日就来操作数据库来完成我的DAO层。
起步
前面记录到,在使用TypeORM
操作数据库时大部分是通过对象的方式来操作的,而不是直接通过编写sql
来操作。当然,这不是绝对的,在某些复杂的场景下,也是会要构建sql
语句来完成数据库的操作。
这里我用到操作数据库的方式是:TypeORM
的实体类仓库管理器开操作,这种方式简单方便,其他的方式也可以访问官网去了解。
在nest中使用
之前说过,在nest
中,我们直接在构造函数中通过这样写就能获取实体的仓库存储器:
constructor(
@InjectRepository(Article)
private readonly articleRepository: Repository<Article>
) {}
现在,就可以通过访问this.articleRepository
来操作数据库了。
查询数据库
当我们获得了实体类的仓库存储器后,就可以通过它来调用对应的API
来操作数据库了,接下来就记录几种常用的操作方式。
find
find
方法文档介绍的非常详细,可以去官网看一下,find
方法直接接受一个conditionns
参数,这个参数里面包含若干查询条件,比如常用的如下。
where
表示查询条件,例如:
article.find({ where: { title: 'Hello Nest' } })
如上,我们就可以找出title
为Hello Nest
的数据,如果没有则返回undefined
。
另外,where
还可以搭配内置运算符使用,例如:
article.find({ where: { title: Like('%Hello%') } })
上面将查出所有title
包含Hello
的数据。
select
表示需要查询的那些字段,没有的字段将会是默认值,例如:
article.find({ select: ['title', 'desc'] });
这样的查询结果,返回的实体类中只有title
和desc
属性中有值。
relations
这个表示关联查询,当我们的表有关联时(一对多,多对一,多对多,该知识点可以看你官网),就可以通过使用该属性非常方便的获取关联对象,例如:
article.find({ relations: ['category'] });
当查询到对应的文章时,会把该文章对应的分类一并查出,并赋值到文章实体类对应的属性中去(这里就是category: Category
)。
skit和take
这两个主要用于分页,take
表示取多少条,而skip
表示跳过多少条,例如这里我要完成一个每页取10条的分页查询就可以这样实现:
articleRepository.find({
skip: (page - 1) * size,
take: size
})
findOne
findOne
文档没怎么记录,通过在findOne
的声明文件中,我们可以找到这样一个方法:
findOne(id?: string | number | Date | ObjectID, options?: FindOneOptions<Entity>): Promise<Entity | undefined>;
可以发现有两个可选参数,第一个是id
,第二个是一个FindOneOptions
的泛型接口,先不管这个。
通过以上定义我们就可以知道:
这个方法是应该是通过id
来查询对应表的一条数据的,其返回是一个Promise
对象或者是一个undefined
。
findAndCount
这个方法一般也是作为分页时用,它除了具有find
方法的功能外,还能查出对应条件的总记录数量(不受take
和skip
分页的影响),并且返回一个数组:第一个参数为find
查询的记录数,第二个为总记录数量,例如:
const [articles, total] = articleRepository.findAndCount();
// articles: Article[]
// total: number
添加/修改数据库
添加和修改数据库的记录,这里我推荐一个API
,就是:save
。
这个API
既可以添加数据,也可以修改数据,其使用区别就是:
当传入实体类有对应的id
时,则为保存数据;没有id
时则为添加数据,例如:
const article = new Article();
article.title = '新增文章';
articleRepository.save(article); // 添加了一条数据,假设生成了id=1的记录
article.id = 1;
article.title = '修改标题';
articleRepository.save(article); // id=1的记录标题被改为了“修改标题”
并且,save
方法是很强大的,当有对应关系的对象存在时,也会给关联的实体对象对应的表添加数据。例如:
// article和tag是多对多关系,因此除了article表还有一张tag表和一张记录tag和article的关联表
const article = new Article();
article.title = '新增文章';
const tag = new Tag();
tag.title = '标签';
article.tags = [tag];
articleRepository.save(article); // 添加了一条数据,并且tag表和关联表也添加了对应数据
删除数据
删除数据非常简单,通过delete
方法即可实现,使用方式有以下三种:
- 直接传入一个
number
:表示删除对应id
的数据; - 传入一个
number[]
:表示删除对应数组内的所有id
的数据; - 传入一个对象:按条件删除,例如:
articleRepository.delete({
title: '标题'
});
总结
以上就是通过实体类的仓库存储器操作数据库的几种简单方式,了解这些方式后就可以比较轻松的做一些基本的CRUD
业务。
其实操作数据库,还有其他的方式,甚至更强大,例如:EntityManager和Query Builder这两种,感兴趣可以看一下。
To Be Continue...