Prisma Crash Course

database Sep 12, 2023
Prisma

In the constantly evolving world of web development, choosing the right tools and frameworks can make all the difference in the world. One tool that has been gaining traction for a while now is Prisma. Prisma is an open-source modern database ORM and toolkit that makes it easier for developers to work with databases and really simplifies the whole process. An ORM is an Object Relational Mapper and instead of interacting with your database using tedious raw SQL queries, you have a nice object-oriented interface that is much cleaner and more enjoyable to work with. If you have ever used something like Sequelize or Mongoose for MongoDB, it's similar to how those work. You can use Prisma for just about anything from REST APIs to GraphQL APIs to CLIs to Full-Stack applications.

It provides type safety and catches data-related errors at runtime. This means you can identify and address potential issues before your code even runs, resulting in more reliable and bug-free applications. You can use Prisma with Regular JavaScript or TypeScript, however, it does encourage TypeScript.

As far as the actual database that you want to use, that's up to you. It's typically used with relational databases like Postgres, MySQL, SQLite, etc However you can also use it with NoSQL databases such as MongoDB. What's cool is your code and your modela aren't going to change based on your database. So you could technically just swap one out for the other by editing the .env file and your database credentials.

It automatically generates code based on your database schema. So if you've ever used something like Sequelize or Mongoose for MongoDB, creating a schema is similar to what you do with those tools. Usually with a relational database, you have to create all your fields with types and tables all on the database level before you even start coding, but with Prisma, you can simply run migrations that will look at your models and create your tables, rows and columns and any constraints that you specify.

3 Parts Of Prisma:

Prisma has three main components and those are the following:

  • Prisma Client - Auto-generated and type-safe query builder for Node.js & TypeScript

You can use Prisma Client with any Node.js or TypeScript application. This includes Full Stack Apps, REST APIs, GraphQL APIs, CLIs, and more. It supports auto-completion and type-checking in your IDE. If you're building a single-page app, you're typically going to use the Prisma client on the server and then create your routes to expose the API endpoints for your frontend to interact with. But one combination that I really like is using Next.js with React server components because you can use the client right from the component.

  • Prisma Migrate - Declarative data modeling & migration system

Prisma Migrate is designed to simplify and automate the process of managing your database schema as your application evolves. It's designed to preserve your existing data during schema migrations. *It generates SQL statements to make the necessary changes to your database while minimizing data loss or downtime.

  • Prisma Studio - GUI to view and edit data in your database

Prisma Studio is the only part of Prisma that is not open-source. It is a GUI that allows you to view and edit data in your database. It is not required to use Prisma, but it is a nice tool to have.

Getting started

Let's go ahead and get started by creating a new folder. I'll call mine prisma-posts. Open that file in your editor or IDE. I'll be using VS Code. You'll need to open a terminal. I'm going to use the built-in terminal in VS Code. You can use any terminal that you want.

Let's initialize a new Node.js project. We can do that by running npm init -y. This will create a new package.json file for us.

We will be creating a TypeScript project, so let's install TypeScript, ts-node, and types for Node.js. We can do that by running the following:

npm install typescript ts-node @types/node -D

ts-node is a TypeScript execution environment for Node.js. It allows us to run .ts files directly without the need to compile them first.

@types/node provides TypeScript type definitions for Node.js core modules and the standard library.

Now, initialize a new TypeScript project by running:

npx tsc --init

This will create a tsconfig.json file for us. Don't worry if you know nothing about TypeScript. We will not be writing any TypeScript code. We are just using it to run our Prisma queries.

Now we can install the Prisma CLI. We can do that by running:

npm install prisma -D

Now let's initialize a new Prisma project. You can use a database like Postres, MySQL or MongoDB, but of course you need to have whatever you use installed on your system. I want everyone to be able to follow along with this tutorial without having to install anything else, so I'm going to use SQLite. The way that we use Prisma and setup our data models is the same no matter what database we use.

We can initialize a new Prisma project and use SQLite as our provider by running:

npx prisma init --datasource-provider sqlite

This will create a new prisma folder for us. Inside of that folder, we will have a schema.prisma file. This is where we will define our data model. There is also a .env file. This is where we will define our database connection. If you were using something like PostgreSQL, you would need to define your database connection in the .env file. Since we are using SQLite, we should already have the following in our .env file:

DATABASE_URL = 'file:./dev.db';

We do not need to create this file. When we run our migration, Prisma will create this file for us.

What Is Data Modeling?

Data modeling is the process of defining the data requirements and structures of a system. It is used to define the data model for a database.

In Prisma, this usually involves describing the database schema, including tables, fields, data types, and their relationships. Effective data modeling in Prisma is crucial because it forms the foundation that your database operations and queries are built, and it ensures that data is structured efficiently, accurately, and in a way that aligns with the needs of the application.

Prisma Schema

The Prisma schema is where you define your data model. It is written in the Prisma schema language. The Prisma schema language is a declarative language that allows you to define your data model and the relationships between your models. It is similar to GraphQL SDL.

Let's open up the schema.prisma file. You should see something like the following:

datasource db {
  provider = "sqlite"
  url      = env("DATABASE_URL")
}

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

The Prisma schema is made up of 3 parts:

  • Datasource - The datasource block is where you define your database connection. You can use any database that Prisma supports. This includes PostgreSQL, MySQL, SQLite, and MongoDB.

  • Generator - The generator block is where you define the Prisma Client generator. This is what generates the Prisma Client for you. You can use any language that Prisma supports. This includes JavaScript, TypeScript, Go, and Rust.

  • Model - The model block is where you define your data model. This is where you define your models and their fields. You can also define relationships between your models.

Let's define User and Article data models:

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

model Article {
  id        Int     @id @default(autoincrement())
  title     String
  body   String?
  author    User    @relation(fields: [authorId], references: [id])
  authorId  Int
}

For the User model we created an id field that is an Int and is the primary key. We also created an email field that is a String and is unique. We created a name field that is a String and added a ? to mark it as an optional field. We also created a articles field that is an array of Article models.

For the Article model we created an id field that is an Int and is the primary key. We also created a title field that is a String. We created a body field that is a String and added a ? to mark it as an optional field. We created an author field that is a User model. We also created an authorId field that is an Int.

We have set our model relationships up so the user can have many articles and an article can only have one author. Also, th authorId field on the Article model references the id field on the User model.

Run Migration

Now that we have our data model defined, we need to run a migration. A migration is a way to update your database schema. It is a way to keep your database schema in sync with your Prisma schema. We can run a migration by running:

npx prisma migrate dev --name init

This command creates a new migration and runs it. The --name flag allows us to give our migration a name. This is optional. If you don't provide a name, Prisma will generate one for you.

If you were using PostgreSQL or something else, you would do the same thing. The only difference is that you would need to define your database connection in the .env file.

Sending Queries via Prisma Client

We can create a new TypeScript file to send queries via Prisma Client. Let's create a new file called index.ts in the root and add the following code:

import { PrismaClient } from '@prisma/client';

const prisma = new PrismaClient();

async function main() {
  // Prisma Queries
}

main()
  .then(async () => {
    await prisma.$disconnect();
  })
  .catch(async (e) => {
    console.error(e);
    await prisma.$disconnect();
    process.exit(1);
  });

Here, we are importing the PrismaClient from @prisma/client and creating a new instance of the PrismaClient. We are also creating an async function called main. Inside of the main function, we will write our Prisma Client queries.

We are also calling the main function and calling the $disconnect method on the prisma instance. This is to disconnect from the database when we are done. We are also catching any errors and logging them to the console.

Let's write a query to create a new user. Add this under the // Prisma Queries comment`:

const user = await prisma.user.create({
  data: {
    name: 'John Doe',
    email: '[email protected]',
  },
});
console.log(user);

To execute this file, we can run:

npx ts-node index.ts

This will create a new user and log the user to the console.

To get the users, we can run:

const users = await prisma.user.findMany();
console.log(users);

Execute the file again and you should see the users in an array logged to the console.

Working With Relationships

Let's create a new article and associate it with a user.

const article = await prisma.article.create({
  data: {
    title: 'Johns First Article',
    body: 'This is Johns first article',
    author: {
      connect: {
        id: 1,
      },
    },
  },
});
console.log(article);

We can get all articles with the following:

const articles = await prisma.article.findMany();
console.log(articles);

Now, lets create a new user and associate it with an article:

const user = await prisma.user.create({
  data: {
    name: 'Sara Smith',
    email: 'sara@gmail.com',
    articles: {
      create: {
        title: 'Saras First Article',
        body: 'This is my first article',
      },
    },
  },
});

Let's get the articles:

const articles = await prisma.article.findMany();
console.log(articles);

Run the file and you should see the articles logged to the console.

If we run the following to get the users:

const users = await prisma.user.findMany();
console.log(users);

You will only see the scalar fields. You will not see the articles field. This is because the articles field is a relation field. To get the relation fields, we need to use the include option. Let's update the query to get the users to include the articles field:

const users = await prisma.user.findMany({
  include: {
    articles: true,
  },
});
console.log(users);

Now you should see the articles field logged to the console. Although it may just say [Object]. This is because the articles field is an array of objects.

Let's loop over the users and log the user and article data to the console:

users.forEach((user) => {
  console.log(`User: ${user.name}, Email: ${user.email}`);
  console.log('Articles:');
  user.articles.forEach((article) => {
    console.log(`- Title: ${article.title}, Body: ${article.body}`);
  });
  console.log('\n');
});

So you can see that Prisma Client makes it easy to work with relationships.

Updating Data

Let's update the user's name:

const user = await prisma.user.update({
  where: {
    id: 1,
  },
  data: {
    name: 'John Doe Jr.',
  },
});
console.log(user);

Removing Data

Let's remove the first article:

const article = await prisma.article.delete({
  where: {
    id: 1,
  },
});

Now if you log the articles or the users with the article, you will see that the article is no longer there.

console.log(articles);
console.log(users);

Prisma Studio

Prisma Studio is a GUI that allows you to view and edit data in your database. It is not required to use Prisma, but it is a nice tool to have. To start Prisma Studio, you can run:

npx prisma studio

This will open Prisma Studio in your browser. From here you can view and edit your data. You can also view your data model and run queries.

As you can see, Prisma makes it simple to work with databases. It is a great tool to have in your tool belt. I hope you enjoyed this crash course on Prisma. If you want to learn more about Prisma, check out the official docs at https://www.prisma.io/docs/.

You can watch the video version here

Stay connected with news and updates!

Join our mailing list to receive the latest news and updates from our team.
Don't worry, your information will not be shared.

We hate SPAM. We will never sell your information, for any reason.