From d5de65fdb1802cdf498d65d93397f290813c377c Mon Sep 17 00:00:00 2001 From: muqiuhan Date: Tue, 9 Sep 2025 06:17:00 +0000 Subject: deploy: 9665097f0fa0dae9f92123fac54d26c0818758a5 --- 2025/02/19/Repository-pattern-in-Typescript/index.html | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) (limited to '2025/02/19') diff --git a/2025/02/19/Repository-pattern-in-Typescript/index.html b/2025/02/19/Repository-pattern-in-Typescript/index.html index c0753a94..99250448 100644 --- a/2025/02/19/Repository-pattern-in-Typescript/index.html +++ b/2025/02/19/Repository-pattern-in-Typescript/index.html @@ -198,30 +198,28 @@

抽象化数据访问层的主要作用是将应用的业务逻辑与对数据库的数据访问等实现细节进行解耦。DB 框架的更改不应该影响到应用程序的核心服务,并且它们应该对业务逻辑代码透明。

业务服务应该只依赖于抽象,而不是实现,数据服务同理。


-

Intro.

例如,此时有一个书籍存储的微服务,并且有一个“添加新书籍”的操作用例,在此用例中可以通过使用 Book 这个 Repository 来添加新书籍,而 Book 具体使用什么数据库,怎么存并不是业务需要关心的事情。

-

具体实现方式

假设有以下实体类型定义:

+

Intro.

+

例如,此时有一个书籍存储的微服务,并且有一个“添加新书籍”的操作用例,在此用例中可以通过使用 Book 这个 Repository 来添加新书籍,而 Book 具体使用什么数据库,怎么存并不是业务需要关心的事情。

+

具体实现方式

+

假设有以下实体类型定义:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
export class Author {
firstName: string;
lastName: string;
}

export class Genre {
name: string;
}

export class Book {
title: string;
author: Author;
genre: Genre;
publishDate: Date;
}
- -

抽象化

第一步是抽象化出一个通用的 Repository ,其中包含通用的操作:

+

抽象化

+

第一步是抽象化出一个通用的 Repository ,其中包含通用的操作:

1
2
3
4
5
6
7
8
9
export abstract class IGenericRepository<T> {
abstract getAll(): Promise<T[]>;

abstract get(id: string): Promise<T>;

abstract create(item: T): Promise<T>;

abstract update(id: string, item: T);
}
- -

接着,定义一个数据服务,其中包含使用 IGenericRepositoiry 定义的具体实例对应的 _Repository_:

+

接着,定义一个数据服务,其中包含使用 IGenericRepositoiry 定义的具体实例对应的 Repository:

1
2
3
4
5
6
7
8
9
10
import { Author, Book, Genre } from '../entities';
import { IGenericRepository } from './generic-repository.abstract';

export abstract class IDataServices {
abstract authors: IGenericRepository<Author>;

abstract books: IGenericRepository<Book>;

abstract genres: IGenericRepository<Genre>;
}
-

以上这些就是对业务中的实体的 Repository 抽象,这样就隔离开了业务和存储逻辑,例如使用 MongoDB,可以实现一个 MongoGenericRepository:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import { Model } from 'mongoose';
import { IGenericRepository } from '../../../core';

export class MongoGenericRepository<T> implements IGenericRepository<T> {
private _repository: Model<T>;
private _populateOnFind: string[];

constructor(repository: Model<T>, populateOnFind: string[] = []) {
this._repository = repository;
this._populateOnFind = populateOnFind;
}

getAll(): Promise<T[]> {
return this._repository.find().populate(this._populateOnFind).exec();
}

get(id: any): Promise<T> {
return this._repository.findById(id).populate(this._populateOnFind).exec();
}

create(item: T): Promise<T> {
return this._repository.create(item);
}

update(id: string, item: T) {
return this._repository.findByIdAndUpdate(id, item);
}
}
-

然后实现一个 MongoDataServices:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
import { Injectable, OnApplicationBootstrap } from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose';
import { Model } from 'mongoose';
import { IDataServices } from '../../../core';
import { MongoGenericRepository } from './mongo-generic-repository';
import {
Author,
AuthorDocument,
Book,
BookDocument,
Genre,
GenreDocument,
} from './model';

@Injectable()
export class MongoDataServices
implements IDataServices, OnApplicationBootstrap
{
authors: MongoGenericRepository<Author>;
books: MongoGenericRepository<Book>;
genres: MongoGenericRepository<Genre>;

constructor(
@InjectModel(Author.name)
private AuthorRepository: Model<AuthorDocument>,
@InjectModel(Book.name)
private BookRepository: Model<BookDocument>,
@InjectModel(Genre.name)
private GenreRepository: Model<GenreDocument>,
) {}

onApplicationBootstrap() {
this.authors = new MongoGenericRepository<Author>(this.AuthorRepository);
this.books = new MongoGenericRepository<Book>(this.BookRepository, [
'author',
'genre',
]);
this.genres = new MongoGenericRepository<Genre>(this.GenreRepository);
}
}
-

Sunday, March 30, 2025 7:58 PM:

感觉以上全错,不应该过度抽象 Repository 的,就让它分散在各个模块中,还可以参考 https://github.com/Papooch/nestjs-cls 实现不会抽象泄漏的事务性 Repository 方法。

-- cgit v1.2.3