Prisma is a modern, type-safe, and highly productive Object-Relational Mapping (ORM) tool that simplifies database access and management for developers. It supports multiple databases, including PostgreSQL, one of the most popular relational databases. In this article, we’ll explore how to use Prisma ORM with PostgreSQL, covering setup, schema definition, CRUD operations, and advanced features.
Why Use Prisma with PostgreSQL?
Prisma offers several advantages when working with PostgreSQL:
Type Safety: Prisma generates TypeScript types based on your database schema, ensuring type safety and reducing runtime errors.
Developer Productivity: Prisma’s intuitive API and auto-generated queries simplify database interactions.
Migrations: Prisma provides a robust migration system to manage schema changes over time.
Database Agnostic: While this article focuses on PostgreSQL, Prisma supports other databases like MySQL, SQLite, and SQL Server.
Real-Time Data: Prisma integrates well with tools like GraphQL and REST APIs, enabling real-time data fetching.
Setting Up Prisma with PostgreSQL
Step 1: Install Prisma
First, ensure you have Node.js installed. Then, create a new Node.js project and install Prisma as a dependency:
mkdir server
cd server
npm init -y
npm install prisma typescript ts-node @types/node --save-dev
Step 2: Initialize Prisma
Initialize Prisma in your project:
npx prisma init
This command creates a prisma
directory with a schema.prisma
file and a .env
file for environment variables.
Step 3: Configure PostgreSQL Connection
Open the .env
file and update the DATABASE_URL
to point to your PostgreSQL database:
DATABASE_URL="postgresql://USER:PASSWORD@HOST:PORT/DATABASE_NAME"
Replace USER
, PASSWORD
, HOST
, PORT
, and DATABASE_NAME
with your PostgreSQL credentials.
Defining Your Database Schema
The schema.prisma
file is where you define your database schema using Prisma’s declarative syntax. Here’s an example schema for a blog application:
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
model User {
id Int @id @default(autoincrement())
email String @unique
name String?
posts Post[]
}
model Post {
id Int @id @default(autoincrement())
title String
content String?
published Boolean @default(false)
authorId Int
author User @relation(fields: [authorId], references: [id])
}
In this schema:
User
andPost
are models representing tables in the database.Relationships are defined using the
@relation
directive.Fields are annotated with attributes like
@id
,@unique
, and@default
.
Applying the Schema to PostgreSQL
To create the tables in your PostgreSQL database, run the following command:
npx prisma migrate dev --name init
This command:
Generates a migration file based on your schema.
Applies the migration to the database.
Creates the
User
andPost
tables.
Performing CRUD Operations with Prisma Client
Prisma Client is an auto-generated query builder that allows you to interact with your database. Let’s explore basic CRUD operations.
1. Create a New User and Post
import { PrismaClient } from '@prisma/client';
const prisma = new PrismaClient();
async function main() {
const user = await prisma.user.create({
data: {
email: 'business.pulkitgarg@gmail.com',
name: 'Pulkit Garg',
posts: {
create: {
title: 'Using Prisma ORM with PostgreSQL...',
content: 'Prisma is a modern...',
},
},
},
});
console.log('Created user with post:', user);
}
main()
.catch((e) => console.error(e))
.finally(async () => await prisma.$disconnect());
2. Fetch All Users with Their Posts
async function main() {
const users = await prisma.user.findMany({
include: { posts: true },
});
console.log('All users with posts:', JSON.stringify(users, null, 2));
}
3. Update a Post
async function main() {
const updatedPost = await prisma.post.update({
where: { id: 1 },
data: { published: true },
});
console.log('Updated post:', updatedPost);
}
4. Delete a User
async function main() {
const deletedUser = await prisma.user.delete({
where: { id: 1 },
});
console.log('Deleted user:', deletedUser);
}
Advanced Features
1. Transactions
Prisma supports transactions for executing multiple operations atomically:
const createUserAndPost = async () => {
await prisma.$transaction([
prisma.user.create({ data: { email: 'business.pulkitgarg@gmail.com', name: 'Pulkit Garg' } }),
prisma.post.create({ data: { title: 'My Second Post Title', authorId: 1 } }),
]);
};
2. Raw SQL Queries
For complex queries, you can use raw SQL:
const users = await prisma.$queryRaw`SELECT * FROM User WHERE name = 'Pulkit Garg'`;
3. Middleware
Prisma allows you to add middleware to intercept queries:
prisma.$use(async (params, next) => {
console.log('Query:', params);
return next(params);
});
4. Data Validation
Prisma integrates with libraries like Zod for additional data validation.
Conclusion
Prisma ORM is a powerful tool for working with PostgreSQL, offering type safety, productivity, and flexibility. By following this guide, you can set up Prisma, define your schema, perform CRUD operations, and leverage advanced features like transactions and raw SQL queries. Whether you’re building a small application or a large-scale system, Prisma simplifies database management and helps you focus on building great software.
For more information, check out the Prisma documentation. Happy coding!