The Importance of Using a Generic Base Service for Database Queries in a Nest.js App with TypeORM (Part1)

Ahmad Alhourani
3 min readSep 28, 2023

--

In modern web development, building robust and maintainable applications is essential. One crucial aspect of application development is managing database operations efficiently. In this article, we will explore the significance of using a generic base service for handling database queries in a Nest.js application with TypeORM.

The Problem

When developing a Nest.js application with TypeORM, you often need to perform various database operations such as saving, updating, finding, and deleting records. To streamline these operations and ensure consistency across your application, it’s a good practice to use a generic base service.

The Solution: Generic Base Service

The provided code defines a generic base service in TypeScript that can be extended for specific entity types. Let’s break down the essential components of this service:

// BaseService.ts

import {
DeepPartial,
FindManyOptions,
FindOneOptions,
Repository,
QueryRunner,
UpdateResult,
SelectQueryBuilder,
} from 'typeorm';
import { Observable, defer, from, map, switchMap } from 'rxjs';
import { QueryDeepPartialEntity } from 'typeorm/query-builder/QueryPartialEntity';

export abstract class BaseService<T> {
constructor(protected readonly repository: Repository<T>) {}

// ... Methods for various database operations
/**
* to save or update an entity
* @param entity
* @returns
*/
save(entity: DeepPartial<T>): Observable<T> {
return defer(() => this.repository.save(entity));
}

/**
*
* @param id
* @param entity
* @returns
*/
update(id: any, entity: QueryDeepPartialEntity<T>): Observable<UpdateResult> {
return defer(() => this.repository.update(id, entity));
}

/**
*
* @param entity
* @param field
* @param incremental
* @returns
*/
increment(
entity: FindOptionsWhere<T>,
field: string,
incremental: number = 1,
): Observable<any> {
return defer(() => this.repository.increment(entity, field, incremental));
}

}

Benefits of Using a Generic Base Service:

  1. Consistency: By using a generic base service, you ensure that all database operations follow the same patterns and conventions. This consistency makes your codebase more maintainable.
  2. Reusability: You can use the same base service for multiple entity types by extending it. This reusability reduces code duplication and simplifies the addition of new entities.
  3. Type Safety: TypeScript’s type inference ensures type safety throughout your code. The generic base service is type-safe, which means it enforces correct data types for each entity.
  4. RxJS Observables: The service methods return RxJS Observables, which allow you to work with asynchronous data in a clean and reactive manner.

Example Usage: Extending the Base Service

Let’s see how you can create a specific service for a Test entity by extending the BaseService:

// TestService.ts

import { Injectable } from '@nestjs/common';
import { Test } from './entities/test.entity';
import { BaseService } from '../../services/base.service';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';

@Injectable()
export class TestService extends BaseService<Test> {
constructor(
@InjectRepository(Test)
protected readonly repository: Repository<Test>,
) {
super(repository);
}
}

Now, you can use the TestService to perform various database operations related to the Test entity, just like in your example:

// Using the TestService

test() {
const input: Partial<Test> = {
type: 'test',
};
return this.testService.save(input);
}

By employing a generic base service, you ensure that database operations in your Nest.js application with TypeORM are consistent, maintainable, and type-safe. This approach enhances the overall quality of your codebase and accelerates development by providing a solid foundation for managing database interactions.

In Part 2 of this series, we will discuss about using transaction manager using TypeORM’s QueryRunner.

Contact Me

--

--

Ahmad Alhourani

https://www.linkedin.com/in/ahmad-alhourani Experienced Software Engineer & Team Lead with 10+ years in RESTful APIs, Microservices,TypeScript, and Blockchain.