Encodera

Thanks for reading!

Donate to the site — we work hard for you.

Contents

Entities and repositories

An entity is a class that describes a table: each property with a decorator becomes a column, and each object a row. A repository is a ready-made TypeORM object with methods for one table: find, save, delete. Instead of the array from chapter two, the posts service will work with a repository.

The post entity

The Post class already lives in src/posts/entities/post.entity.ts. Add TypeORM decorators to it:

// src/posts/entities/post.entity.ts
import { Column, CreateDateColumn, Entity, PrimaryGeneratedColumn } from 'typeorm';
 
@Entity()
export class Post {
  @PrimaryGeneratedColumn()
  id: number;
 
  @Column({ length: 120 })
  title: string;
 
  @Column('text')
  content: string;
 
  @CreateDateColumn()
  createdAt: Date;
}
DecoratorWhat it creates
@Entity()The post table
@PrimaryGeneratedColumn()A primary key the database increments itself
@Column()A regular column; the type comes from TypeScript
@Column('text')A column with an explicit type
@CreateDateColumn()A creation date filled in automatically

Registering in the module

The posts module tells TypeORM about its entity:

// src/posts/posts.module.ts
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { Post } from './entities/post.entity';
import { PostsController } from './posts.controller';
import { PostsService } from './posts.service';
 
@Module({
  imports: [TypeOrmModule.forFeature([Post])],
  controllers: [PostsController],
  providers: [PostsService],
})
export class PostsModule {}

After saving, the server restarts, and thanks to synchronize: true the blog.sqlite file gets a post table with the columns id, title, content and createdAt.

The repository in the service

forFeature() creates the repository, and the @InjectRepository() decorator injects it into the service:

// src/posts/posts.service.ts
import { Injectable, NotFoundException } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { CreatePostDto } from './dto/create-post.dto';
import { Post } from './entities/post.entity';
 
@Injectable()
export class PostsService {
  constructor(
    @InjectRepository(Post)
    private readonly postsRepository: Repository<Post>,
  ) {}
 
  findAll(): Promise<Post[]> {
    return this.postsRepository.find({ order: { createdAt: 'DESC' } });
  }
 
  async findOne(id: number): Promise<Post> {
    const post = await this.postsRepository.findOneBy({ id });
    if (!post) {
      throw new NotFoundException(`Post ${id} not found`);
    }
    return post;
  }
 
  create(dto: CreatePostDto): Promise<Post> {
    const post = this.postsRepository.create(dto);
    return this.postsRepository.save(post);
  }
}

All repository methods are asynchronous and return promises. The controller does not change: NestJS waits for the promise itself. Create a post with a POST request, restart the server and open /posts — the post is still there.

Main repository methods

MethodWhat it does
find(options)A list of rows with conditions, ordering, limits
findOneBy({ id })One row or null
create(data)A new, not yet saved entity object
save(entity)Inserts a new row or updates an existing one
update(id, data)Changes fields without loading the object
delete(id)Deletes a row by key
count(options)The number of rows

Common mistake

The error Nest can't resolve dependencies of the PostsService (?) mentioning PostRepository means the module is missing TypeOrmModule.forFeature([Post]). A repository exists only in modules that registered the entity. If another module needs the repository, add forFeature() there too or export the service that works with it.

Thanks for reading!

Donate to the site — we work hard for you.