What are ORMs? & Understanding Prisma and its Implementing
Official Definition
ORM stands for Object-Relational Mapping, a programming technique used in software development to convert data between incompatible type systems in object-oriented programming languages. This technique creates a "virtual object database" that can be used within the programming language.
In simpler terms, ORMs abstract the complexities of interacting with the underlying database, allowing developers to work with data using familiar object-oriented paradigms instead of raw SQL.
Straightforward Definition
ORMs let you interact with your database in a straightforward way without worrying too much about SQL or other database-specific syntax.
Why Use ORMs?
1. Simpler Syntax
ORMs provide an intuitive, readable syntax for querying and manipulating data, minimizing the need to write raw SQL queries.
2. Database Abstraction
ORMs enable database independence, allowing you to switch between different database systems (e.g., PostgreSQL, MySQL, MongoDB) with minimal changes. Typically, you only need to update the database connection string or configuration.
3. Type Safety and Autocompletion
Modern ORMs (e.g., Prisma) provide type-safe APIs and autocompletion in your IDE, reducing errors and improving developer productivity.
4. Automatic Migrations
Keeping track of changes to your database schema can be challenging in larger projects. ORMs like Prisma simplify this with automated migrations. They track schema changes, generate migration scripts, and ensure that your database schema matches your application’s data model.
What is Prisma?
Prisma is an advanced ORM that enhances the developer experience when working with databases. With features like an intuitive data model, automated migrations, type safety, and autocompletion, Prisma significantly streamlines database interactions.
Workflow
Key Features of Prisma
1. Intuitive Data Modeling
In Prisma, you define your database schema in a single file. This schema includes details such as:
Tables
Fields for each table
Relationships between tables (e.g., one-to-one, one-to-many)
Here’s an example of a Prisma schema:
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
model User {
id Int @id @default(autoincrement())
email String @unique
username String @unique
password String
fullname String
phone Int?
todos Todos[]
}
model Todos {
id Int @id @default(autoincrement())
title String
description String
done Boolean @default(false)
user_id Int
user User @relation(fields: [user_id], references: [id])
}
This schema defines two tables (User
and Post
) and their relationship (one user can have many posts).
2. Automated Migrations
Prisma’s migration system helps you manage changes to your database schema seamlessly. When you modify your data model, Prisma generates migration files to update the database structure accordingly. This ensures consistency between your application code and database schema.
Refer to the diagram above for a better understanding.
Defining Relationships with Prisma
Prisma simplifies defining and managing relationships between tables. It supports the following types of relationships:
1. One-to-One
Each record in Table A is related to one record in Table B. Example: A user profile linked to a user account.
2. One-to-Many
A record in Table A can have multiple related records in Table B. Example: A user having multiple posts.
3. Many-to-One
This is the inverse of one-to-many. Example: Multiple posts belonging to a single user.
4. Many-to-Many
Records in Table A can be associated with multiple records in Table B, and vice versa. Example: Users belonging to multiple groups.
e.g., In the TODO app, there is a one-to-many relationship
Generating the Prisma Client
The Prisma Client is an auto-generated library tailored to your data model. It provides a type-safe API to interact with your database. Refer to the diagram above for a better understanding. For example:
import { PrismaClient } from "@prisma/client";
const prisma = new PrismaClient();
// Inserting data into the database
async function insertUser(
email: string,
username: string,
password: string,
fullname: string
) {
const res = await prisma.user.create({
data: {
email,
username,
password,
fullname,
},
select: {
id: true,
email: true,
username: true,
password: true,
fullname: true,
},
});
console.log(res);
}
// Updating data in the database
async function updateUser(
id: number,
email: string,
username: string,
password: string,
fullname: string
) {
const res = await prisma.user.update({
where: {
id,
},
data: {
email,
username,
password,
fullname,
},
select: {
id: true,
email: true,
username: true,
password: true,
fullname: true,
},
});
console.log(res);
}
// Getting data from the database
async function getUser(username: string) {
const user = await prisma.user.findFirst({
where: {
username: username,
},
});
console.log(user);
}
getUser("AmanOG");
insertUser("jaman5763@gmail.com", "Aman", "123456", "Aman Jaiswal")
updateUser(2, "jaman@gmail.com", "AmanOG", "123456", "Aman Jaiswal")
// Relationship
async function createTodo(user_id: number, title: string, description: string) {
const todo = await prisma.todos.create({
data: {
title,
description,
user_id,
},
});
console.log(todo);
}
createTodo(1, "go to gym", "go to gym and do 10 pushups");
async function getTodos(user_id: number) {
const todos = await prisma.todos.findMany({
where: {
user_id: user_id,
},
});
console.log(todos);
}
getTodos(1);
// one way to do this is to get user details and then get todos of that user
async function getTodosAndUserDetails(user_Id: number) {
const user = await prisma.user.findUnique({
where: {
id: user_Id
}
});
const todos = await prisma.todos.findMany({
where: {
user_id: user_Id,
}
});
console.log(todos);
console.log(user)
}
getTodosAndUserDetails(1);
// better way to do this using joins
async function getTodosAndUserDetailss(user_id: number, ) {
const todos = await prisma.todos.findMany({
where: {
id: user_id,
},
select: {
user: true,
title: true,
description: true
}
});
console.log(todos);
}
getTodosAndUserDetailss(1);
For code checkout, visit: https://github.com/JAmanOG/Tried-Prisma