DEV Community

Cover image for What is Object–Relational Mapping? Why Prisma?
Madhan M
Madhan M

Posted on

What is Object–Relational Mapping? Why Prisma?

This article will explain what an object relational mapping (ORM) is, and why you should consider using one with your next project. We’ll also evaluate one of the best ORMs.

Table of Contents:

  1. What is an ORM?
  2. ORM Libraries
  3. Pros of using an ORM
  4. Cons of using an ORM:
  5. List of Popular Node.js ORMs
  6. Choosing an ORM
  7. What is Prisma? What does it offer?
  8. SetUp and Implementation
  9. Why Prisma?
  10. Conclusion

In today’s world, “data” is omnipresent. From Big Data to Data Science - it is everywhere. This data can be present in a spreadsheet or a database like MySQL, SQLite, etc.

Software developers and Engineers use databases to store data and use SQL Queries to fetch and manipulate data. For example:
An Example of a Database
To get the student data with ID 184, we write a simple SQL query like this,

select Name from Students where ID=184;
Enter fullscreen mode Exit fullscreen mode

However, in reality as an application gets bigger, the SQL queries gets complex.

Further, the queries not only become longer in size and complicated but also difficult to comprehend. To add more to the developer’s problems, there exist multiple ways to write them which only makes it more difficult to understand. This is where ORMs come to our rescue!

What is an ORM?

Object-Relational Mapping is a technique that lets you query and manipulates data from a database using an object-oriented paradigm. ORM loves objects as much as developers, and is available for any programming language of your choosing.

ORMs can be thought of as a translator converting our code from one form to another.

ORM

The Object-Relational Mapper generates objects (as in OOP) that virtually map the tables in your database. Then the programmer would use these objects to interact and play with the database! So the core idea is to try and shield the programmer from having to write optimized and complex SQL code.

If you’re building a small project, installing an ORM library isn’t required. Using SQL statements to drive your application should be sufficient. An ORM is quite beneficial for medium to large-scale projects that source data from hundreds of database tables. In such a situation, you need a framework that allows you to operate and maintain your application’s data layer in a consistent and predictable way.

ORM Libraries

Object relational mapping is commonly undertaken with help of a library. The term ORM most commonly refers to an actual ORM library — an object relational mapper, that carries out the work of object relational mapping for you.

An object-relational mapper provides an object-oriented layer between relational databases and object-oriented programming languages without having to write SQL queries.

Pros of using an ORM:

  • They write correct and optimized SQL queries, thereby eliminating the hassle for developers
  • They make the code easier to update, maintain, and reuse as the developer can think of, and manipulate data as objects.
  • It standardizes interfaces reducing boilerplate and speeding development time.
  • ORMs will shield your application from SQL injection attacks since the framework will filter the data for you!
  • ORMs provide the concept of Database Abstraction which makes switching databases easier and creates a consistent code base for your application.

Cons of using an ORM:

  • Performance: A common complaint among OOP developers is the extra code generated by the ORM which slows application performance and makes it harder to maintain. A well-designed ORM should be able to create high-quality code without affecting application speed.
  • Reliability: High-level abstractions do not always generate the best SQL code, and developers cannot rely on the ORM 100 percent of the time. Hence, you still need to know SQL as well as the syntax generated by the ORM. (Isn't it contradicting?)
  • Effects on Schema and Migrations: A poorly-written ORM layer often makes it challenging to improve data schemas. It can often limit your choices and depending on the ORM, your options may be limited. If your ORM doesn’t support migrations, writing the migrations in your OOP is more complicated than writing the code for migrations in SQL. A well-written ORM will include tools to facilitate future database migrations.
  • Poor Mapping: ORMs can sometimes create an incorrect mapping between data tables and objects(In poorly maintained ORMs). These problems can cause application problems and be difficult to recognize.

Know more about Problems with SQL, ORMs and other database tools here

ORMs are powerful tools. The ORMs we’ll be examining in this post are able to communicate with SQL backends such as SQLite, PostgreSQL, MySQL and SQL Server. Also we'll be looking at ORMs capable of communicating with NoSQL backends, such as MongoDB.

List of Popular Node.js ORMs :

Choosing an ORM:

An ORM is just like any other software package. You'll need to compare multiple things, it's not all about what it can and can't. Let's think about:

  • More features to choose from,
  • Documentation,
  • Performance/Speed,
  • Community,
  • Support,
  • Development progress, Future proof?

In this article, we'll see why Prisma is the best!

What is Prisma? What does it offer?

Prisma is an open source next-generation Node.js and TypeScript ORM. It describes itself as a “next-generation ORM” that makes working with databases easy for application developers.

Prisma.png

Prisma provides the following tools:

Prisma is very different from all the other ORMs because, it doesn’t use object models (entity classes), but rather a schema file to map all the tables and columns. This file is used by the migration tool to generate an SQL migration file and the client library to generate type definitions.

All generated type definitions are stored in a .prisma/client/index.d.ts folder.

Traditional ORMs provide an object-oriented way for working with relational databases by mapping tables to model classes in your programming language. This approach leads to many problems that are caused by the object-relational impedance mismatch.

SetUp and Implementation

Setting up a Prisma project is a bit of a process, which you can find the full instructions in Prisma Docs.

For now, we’re simply just evaluating with a simple example. Here are the basic installation steps:

After creating a project directory, initialize a TypeScript project and add the Prisma CLI as a development dependency to it:

npm init -y
npm install prisma typescript ts-node @types/node --save-dev
Enter fullscreen mode Exit fullscreen mode

This creates a package.json with an initial setup for your TypeScript app. Next, create a tsconfig.json file and add the following configuration to it:

{
  "compilerOptions": {
    "sourceMap": true,
    "outDir": "dist",
    "strict": true,
    "lib": ["esnext"],
    "esModuleInterop": true
  }
}
Enter fullscreen mode Exit fullscreen mode

Now create your application’s data model in the schema file located at prisma/schema.prisma:

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

model Post {
  id        Int      @default(autoincrement()) @id
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt
  title     String   @db.VarChar(255)
  content   String?
  published Boolean  @default(false)
  author    User     @relation(fields: [authorId], references: [id])
  authorId  Int
}

model Profile {
  id     Int     @default(autoincrement()) @id
  bio    String?
  user   User    @relation(fields: [userId], references: [id])
  userId Int     @unique
}

model User {
  id      Int      @default(autoincrement()) @id
  email   String   @unique
  name    String?
  posts   Post[]
  profile Profile?
}
Enter fullscreen mode Exit fullscreen mode

Next, you’ll need to map your data model to the database schema using prisma migrate CLI tool:

npx prisma migrate dev --name init --preview-feature
Enter fullscreen mode Exit fullscreen mode

Let us look at our setup code in index.ts:

// Import the PrismaClient constructor from the @prisma/client node module
import { PrismaClient } from '@prisma/client'

// Instantiate PrismaClient
const prisma = new PrismaClient()

// Define an async function named main to send queries to the database
async function main() {
  // Here you will write your Prisma Client queries here
  //findMany API query returns all User records
  const allUsers = await prisma.user.findMany() 
  console.log(allUsers)
}

main()
  .catch(e => {
    throw e
  })
  .finally(async () => {
    await prisma.$disconnect()
  })
Enter fullscreen mode Exit fullscreen mode

Below is a sample demonstrating how to persist data and query records:

async function main() {
  //Create a single record
  await prisma.user.create({
    data: {
      name: 'Alice',
      email: 'alice@prisma.io',
      posts: {
        create: { title: 'Hello World' },
      },
      profile: {
        create: { bio: 'I love Programming' },
      },
    },
  })

  //findMany API returns a list of records.
  const allUsers = await prisma.user.findMany({
    include: {
      posts: true,
      profile: true,
    },
  })
  console.dir(allUsers, { depth: null })
}
Enter fullscreen mode Exit fullscreen mode

When you run the above code, the results will be returned as JavaScript objects like this:

[
  {
    email: 'alice@prisma.io',
    id: 1,
    name: 'Alice',
    posts: [
      {
        content: null,
        createdAt: 2021-08-21T09:35:01.246Z,
        id: 1,
        published: false,
        title: 'Hello World',
        authorId: 1,
      }
    ],
    profile: {
      bio: 'I love Programming',
      id: 1,
      userId: 1,
    }
  }
]
Enter fullscreen mode Exit fullscreen mode

Follow this to set up Prisma and start from scratch ->Prisma getting started

Why Prisma?

Prisma's main benefit is to provide an abstraction layer that makes you more productive compared to writing SQL.

Now the question remains why you should use Prisma in the first place. Here are some reasons why developers should consider using Prisma and where it can be of help.

Typesafe:

Prisma provides a type-safe API that can be used from the front and backend including filters, aggregations, and transactions. This drastically increases the intelligent auto-completion or jump-to-definition features of IDEs and also makes code generation easier.

Simple database workflows:

Prisma’s overall goals are to remove complexity from database workflows and simplify data access in your applications by providing:

  • Simple and powerful API for working with relational data:
  • Visual data management using Prisma Admin
  • Automatic database migrations
  • Easy data import and export

Clean and layer architecture:

Prisma provides a clean architecture which respects synchronization, query optimization/performance and security. They do so by providing a build-in DAT (data access layer) which is used to abstract the complexity of the database access so that the developers can focus on their data instead of worrying about how to store and retrieve it from the database.

Well-maintained Documentation

Prisma’s documentation looks pretty, and it appears to have a lot of content.
Information is spread over multiple sections, including:

  • concepts
  • guides
  • reference
  • support/help articles

Well-documented library, great support, growing community and constantly working on new features.

Prisma's main goal is to make application developers more productive when working with databases. Here are a few examples of how Prisma achieves this:

  • Thinking in objects instead of mapping relational data
  • Queries not classes to avoid complex model objects
  • Single source of truth for database and application models
  • Healthy constraints that prevent common pitfalls and antipatterns
  • An Abstraction that makes the right thing easy ("pit of success")
  • Type-safe database queries that can be validated at compile time
  • Less boilerplate so developers can focus on the important parts of their app
  • Auto-completion in code editors instead of needing to look up documentation (Source: Prisma Docs)

Check out this page to see if Prisma likely is a good fit for you ->Should you use Prisma?

Check out the below links to compare:

TypeORM vs Prisma

Sequelize vs Prisma

Mongoose vs Prisma

Conclusion

Prisma is a newer library that follows a different philosophy on data layer building. After all, developers should only care about the data they need to implement a feature and not spend time figuring out complicated SQL queries to fit their needs.

Prisma makes it easy for developers to reason about their database queries by providing a clean and type-safe API for submitting database queries which returns plain old JavaScript objects.

Since, Prisma is reliable, well-Documented, and resolves most of the cons of using an ORM, I consider Prisma as the best TypeScript ORM.

You made it all the way until the end! Hope that this article helped you understand the concept of ORMs, it's pros and cons, an overview of Prisma with an example and why it is so useful to us backend developers.

Checkout this playlist to Learn how to build a fullstack app! With Next.js, GraphQL, TypeScript & Prisma

Also checkout Prisma Day 2021 and Prisma Features Highlights

Have a wonderful experience trying to learn some more using the Prisma Documentations

Discussion (0)