DEV Community

Marc Stammerjohann for notiz.dev

Posted on • Originally published at notiz.dev on

How to query your database using Prisma with NestJS

Prisma is a toolkit for modeling, querying and migrating a database. Prisma 2.0 is currently rewritten with Rust and hit recently the first Beta release 🎉. Find out if Prisma 2.0 is production ready.

Nestjs is a popular typescript server-side application framework. It is heavily influenced by Angular's architectur and enables to create a REST and Graphql backend.

This guide shows how to setup a NestJS application querying data from a SQLite database using Prisma 2.0.

TL;DR

Add Prisma to a Nest application and generate a PrismaClient. Create a Nest PrismaService which extends PrismaClient and handles the connection using Nest lifecycle events. Inject PrismaService into REST controllers or Graphql resolvers to query your data models.

Step 1: Start a new Nestjs application

Generate a new Nest application or skip to the next step if you follow along with an existing Nest project.

To generate a new Nest application use the nest cli:

npm i -g @nestjs/cli
nest new project-name

Enter fullscreen mode Exit fullscreen mode

Change your directory into the newly created Nest application and open up your prefered IDE.

Step 2: Add Prisma 2.0

Add Prisma 2.0, create an empty prisma.schema file and install prisma-client-js to your Nest application.

npm install @prisma/cli --save-dev
npx prisma init

npm install @prisma/client

Enter fullscreen mode Exit fullscreen mode

Step 3: Update Prisma datasource

In this guide we are connecting to a SQLite database. Update the provider in the prisma/prisma.schema to sqlite and change the url environment to file:./dev.db. Prisma Migrate will create a SQLite database at prisma/dev.db.

The prisma.schema should look like:

datasource db {
  provider = "sqlite"
  url = "file:./dev.db"
}

generator client {
  provider = "prisma-client-js"
}

Enter fullscreen mode Exit fullscreen mode

Step 4: Define a model

Now we define a model for the database. A simple User model looks like:

model User {
  id Int @id @default(autoincrement())
  email String @unique
  name String?
}

Enter fullscreen mode Exit fullscreen mode

We are adding the above model to prisma.schema below the generator.

For more complex models check out Prisma's data modeling definition.

Step 5: Create SQLite database with Migrate

We are creating our first database migration using the experimental Prisma Migrate. First we save a migration using npx prisma migrate save --experimental. Prisma asks us to create the dev.db database and we select Yes. Next we provide a name for the migration, for example user as we just define the User model.

Now we can apply the migration with npx prisma migrate up --experimental.

Warning: Prisma Migrate is considered experimental those we need to provide the --experimental flag.

Step 6: Generate PrismaClient

For each change we make to the data model of prisma.schema, we have to generate the PrismaClient again.

Run the following command to generate a new PrismaClient which contains the CRUD operations for the new User model:

npx prisma generate

Enter fullscreen mode Exit fullscreen mode

Step 7: Create a Prisma service

SQLite database is setup and a User model is defined with Prisma. Now its time to prepare our Nestjs application to query the database using prisma-client-js.

We are creating a Nestjs service prisma which will extend the PrismaClient to instantiate the connection.

nest generate service prisma

Enter fullscreen mode Exit fullscreen mode

Our PrismaService looks like this:

import { Injectable } from '@nestjs/common';
import { PrismaClient } from '@prisma/client';

@Injectable()
export class PrismaService extends PrismaClient {
  constructor() {
    super();
  }
}

Enter fullscreen mode Exit fullscreen mode

PrismaClient allows us to handle the connection ourselves using connect() and disconnect(). We will make use of Nest Lifecycle Events OnModuleInit and OnModuleDestroy to take care of the connection for us.

Our updated PrismaService with the lifecycle events looks like:

import { Injectable, OnModuleInit, OnModuleDestroy } from '@nestjs/common';
import { PrismaClient } from '@prisma/client';

@Injectable()
export class PrismaService extends PrismaClient
  implements OnModuleInit, OnModuleDestroy {
  constructor() {
    super();
  }

  async onModuleInit() {
    await this.connect();
  }

  async onModuleDestroy() {
    await this.disconnect();
  }
}

Enter fullscreen mode Exit fullscreen mode

Step 8: Query data model

Now we can inject the PrismaService into any REST controller, Graphql resolver or service to query our data model. We will inject it into a controller and create REST endpoints querying and creating User models.

Note we are directly accessing the type-safe generated Api from the PrismaClient through PrismaService.

import { Controller, Get, Param, Post, Body } from '@nestjs/common';
import { AppService } from './app.service';
import { PrismaService } from './prisma/prisma.service';
import { CreateUserDto } from './create-user.dto';

@Controller()
export class AppController {
  constructor(
    private readonly appService: AppService,
    private readonly prisma: PrismaService
  ) {}

  @Get()
  getHello(): string {
    return this.appService.getHello();
  }

  @Get('users')
  async users() {
    return await this.prisma.user.findMany();
  }

  @Get('users/:id')
  async user(@Param('id') id: string) {
    return await this.prisma.user.findOne({ where: { id: +id } });
  }

  @Post('user')
  async addUser(@Body() createUserDto: CreateUserDto) {
    return await this.prisma.user.create({ data: createUserDto });
  }
}

Enter fullscreen mode Exit fullscreen mode

Now its time to continue updating your data model, generating PrismaClient and adding queries to your Nest application.

Checkout nestjs-prisma-starter to get started quickly with Nest and Prisma.

For more posts checkout notiz.dev.

Top comments (0)