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;
}| Decorator | What 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
| Method | What 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.