Prisma ORM Full Course 2025 | Become a Prisma Pro in 2.5 Hours

PedroTechAbout 9 min readJun 11, 2025Watch original
THE SUMMARYAI-generated

Key Concepts

  • ORM (Object-Relational Mapping): A technique that lets you query and manipulate data from a database using an object-oriented paradigm.
  • Prisma Schema: A file defining database models, relationships, and configurations using Prisma's syntax.
  • Prisma Client: A type-safe query builder generated from the Prisma schema, enabling interaction with the database.
  • Migrations: A history of changes made to the database schema.
  • Seeding: Populating the database with initial data for testing or development.
  • CRUD Operations: Create, Read, Update, and Delete operations on data.
  • Relations: Connections between different models in the database.
  • Server Actions: Functions that run on the server, often used for database interactions.
  • API Routes: Endpoints in a Next.js application that handle server-side logic.
  • NextAuth.js (NextAuth): An authentication library for Next.js applications.
  • JWT (JSON Web Token): A standard for securely transmitting information between parties as a JSON object.

Prisma Crash Course for Beginners: Building a Full-Stack Job Posting App

Introduction to Prisma

  • Prisma is a powerful ORM for JavaScript and TypeScript, simplifying database interactions with a type-safe API.
  • ORMs allow developers to use code (JavaScript functions) instead of writing SQL manually.
  • Benefits of using an ORM:
    • Easier to read and write data.
    • Safer (prevents SQL injections).
    • Faster development (reduces repetitive SQL code).
    • Type safety through clear models.
  • Prisma's strengths: Type safety, performance, and community support.

Setting Up a Project with Prisma

  • A starter Node.js Express server project is provided for initial Prisma exploration.
  • Installation:
    • npm install prisma (generic Prisma library).
    • npm install @prisma/client (for interacting with Prisma in JavaScript/TypeScript).
  • Initialization:
    • npx prisma init (generates the Prisma schema and other necessary files).
  • Prisma Extension: Install the Prisma extension for syntax highlighting in .prisma files.
  • Prisma Schema File:
    • Defines the database schema and connection details.
    • Includes the database provider (e.g., PostgreSQL).
    • Specifies the database URL.
  • Database Hosting: Neon (neon.tech) is used as a free serverless PostgreSQL database provider.
  • Environment Variables: Database URL should be stored in a .env file, not directly in the schema.

Understanding the Prisma Schema

  • Key keywords:
    • generator: Tells Prisma to generate client code.
    • datasource: Specifies the database connection.
    • model: Defines database tables and their fields.
  • Example: User Model
    • model User { ... }
    • id Int @id @default(autoincrement()) (defines an auto-incrementing integer ID as the primary key).
    • name String (defines a string field for the user's name).
    • email String @unique (defines a unique string field for the user's email).
    • createdAt DateTime @default(now()) (defines a datetime field that defaults to the current time).

Migrations and Database Updates

  • Migrating the schema:
    • npx prisma migrate dev --name init (applies schema changes to the database in development).
    • Creates a migrations folder to track schema changes.
  • Generating the Prisma Client:
    • npx prisma generate (generates the type-safe Prisma client code).

Seeding the Database

  • Creating a seed.ts file to populate the database with initial data.
  • Importing the PrismaClient class from @prisma/client.
  • Creating an instance of the PrismaClient: const prisma = new PrismaClient().
  • Using prisma.user.createMany() to add multiple users to the database.
  • Example:
    async function seed() {
      await prisma.user.createMany({
        data: [
          { name: 'Alice', email: '[email protected]' },
          { name: 'Bob', email: '[email protected]' },
        ],
      });
    }
    
  • Running the seed command: npx prisma db seed.
  • Defining a prisma.seed script in package.json to execute the seed file.
  • Error handling: Demonstrating how unique constraints prevent adding duplicate emails.

Building a Simple API with Prisma

  • Using Express to create API endpoints.
  • Importing the PrismaClient in index.ts.
  • Creating an instance of the PrismaClient.
  • Find Functions:
    • findFirst(): Returns the first item in the table.
    • findFirstOrThrow(): Returns the first item or throws an error if not found.
    • findMany(): Returns all items in the table.
    • findUnique(): Returns a unique item based on a unique field (e.g., ID or email).
  • Example: Getting all users
    app.get('/users', async (req, res) => {
      const users = await prisma.user.findMany();
      res.json(users);
    });
    
  • Where Condition: Using the where condition to filter data based on specific criteria.
  • Comparison Operators:
    • lt (less than).
    • lte (less than or equal to).
    • gt (greater than).
    • gte (greater than or equal to).
  • Logical Operators:
    • or: Returns items matching any of the specified conditions.
    • and: Returns items matching all of the specified conditions.
    • not: Negates a condition.
  • In Operator: Checking if a field is part of a set of values using the in property.

Updating and Deleting Data

  • Updating a user:
    • Using the update() function.
    • Specifying the user to update using the where property with a unique field.
    • Providing the data to update using the data property.
    • Example:
      app.put('/users', async (req, res) => {
        const updatedUser = await prisma.user.update({
          where: { email: '[email protected]' },
          data: { age: 35, isMarried: true },
        });
        res.json(updatedUser);
      });
      
  • Deleting a user:
    • Using the delete() function.
    • Specifying the user to delete using the where property with a unique field.
    • Example:
      app.delete('/users', async (req, res) => {
        const deletedUser = await prisma.user.delete({
          where: { email: '[email protected]' },
        });
        res.json(deletedUser);
      });
      
  • Deleting Many Users:
    • Using the deleteMany() function.
    • Specifying the condition for deletion using the where property.
    • Example: Deleting all users with age greater than 30.

Building a Job Posting Website with Next.js and Prisma

  • Project Setup:
    • Using a starter Next.js project with pre-defined CSS and assets.
    • Installing necessary dependencies: prisma, @prisma/client, next-auth, @next-auth/prisma-adapter, date-fns.
  • Database Setup:
    • Using the same Neon database from the previous section.
    • Deleting existing tables and the prisma/migrations folder.
    • Running npx prisma init to initialize Prisma in the project.
  • Authentication with NextAuth.js:
    • Setting up models for Account, Session, and VerificationToken as required by NextAuth.js.
    • Creating a User model with fields like id, name, email, image, and relations to Account and Session.
  • Job Model:
    • Defining a Job model with fields like id, title, companyName, location, type, description, salary, postedAt, and a relation to the User model (postedBy).
  • Application Model:
    • Defining an Application model with fields like id, jobId, userId, status, appliedAt, and relations to both User and Job models.
    • Implementing a composite unique constraint on the Application model to ensure that a user can only apply to a job once.
  • Database Migrations:
    • Running npx prisma migrate dev --name init to create the tables in the database.
    • Running npx prisma generate to generate the Prisma client.
  • Navbar Component:
    • Creating a Navbar component with links to browse jobs, post a job, view the dashboard, and sign in/sign out.
    • Using Tailwind CSS for styling.
  • Sign-in Page:
    • Creating a SignInPage component with a button to sign in with GitHub.
    • Using Tailwind CSS for styling.
  • NextAuth.js Configuration:
    • Creating an auth.ts file at the root of the project to configure NextAuth.js.
    • Specifying the session strategy (JWT), providers (GitHub), and adapter (Prisma).
    • Implementing jwt and session callbacks to enrich the JWT token and session with user information.
  • Middleware Configuration:
    • Creating a middleware.ts file to export the auth object from auth.ts for Next.js to recognize.
  • API Route for NextAuth.js:
    • Creating an api/auth/[...nextauth]/route.ts file to handle NextAuth.js requests.
    • Using the handlers object from auth.ts to create GET and POST request handlers.
  • Server Actions for Authentication:
    • Creating a lib/auth.ts file to define server actions for logging in and logging out.
    • Using the signIn and signOut functions from NextAuth.js.
  • Environment Variables for GitHub Authentication:
    • Generating an OAuth secret using npm exec nextauth secret.
    • Creating a GitHub OAuth app and obtaining a client ID and client secret.
    • Setting the AUTH_GITHUB_ID and AUTH_GITHUB_SECRET environment variables in .env.local.
  • Session Provider:
    • Creating a SessionProvider component to provide the session to all client components.
    • Using the useSession hook from NextAuth.js to access the session in client components.
  • Conditional Rendering in Navbar:
    • Using the session object to conditionally render the sign-in/sign-out button and other links based on the user's authentication status.
  • Post Job Page:
    • Creating a PostJobPage component with a form to create a new job.
    • Using Tailwind CSS for styling.
  • API Route for Creating a Job:
    • Creating an api/jobs/route.ts file to handle the creation of new jobs.
    • Authenticating the user using the auth function.
    • Extracting the job data from the request body.
    • Creating a new job in the database using prisma.job.create().
  • Handling Form Submission:
    • Creating a handleSubmit function in the PostJobPage component to handle the form submission.
    • Making a POST request to the api/jobs endpoint with the job data.
    • Redirecting the user to the /jobs route after successful job creation.
  • Browse Jobs Page:
    • Creating a JobsPage component to display a list of jobs.
    • Fetching the jobs from the database using prisma.job.findMany().
    • Ordering the jobs by postedAt in descending order.
    • Including the postedBy relation to get the user information for each job.
  • Search Functionality:
    • Implementing search functionality using the searchParams prop in the JobsPage component.
    • Using the where condition in prisma.job.findMany() to filter the jobs based on the search query, type, and location.
    • Using the or operator to search for jobs where the title, company name, or description contains the search query.
    • Using the mode: insensitive option to perform case-insensitive searches.
  • Job Details Page:
    • Creating a JobPage component to display the details of a specific job.
    • Fetching the job from the database using prisma.job.findUnique() with the job ID.
    • Including the postedBy relation to get the user information for the job.
    • Using the formatDistanceToNow function from date-fns to format the postedAt date.
  • Apply Button Component:
    • Creating an ApplyButton component to allow users to apply for a job.
    • Using the useSession hook to check if the user is authenticated.
    • Redirecting the user to the sign-in page if they are not authenticated.
  • API Route for Applying for a Job:
    • Creating an api/jobs/[id]/apply/route.ts file to handle the application process.
    • Authenticating the user using the auth function.
    • Checking if the job exists.
    • Checking if the user has already applied for the job.
    • Creating a new application in the database using prisma.application.create().
  • Dashboard Page:
    • Creating a DashboardPage component to display the user's posted jobs and applications.
    • Fetching the user's posted jobs and applications from the database using prisma.job.findMany() and prisma.application.findMany().
    • Using Promise.all() to fetch both the posted jobs and applications concurrently.
    • Including the job and postedBy relations in the applications query to get the job and user information.
    • Using the _count property to get the number of applications for each posted job.
  • Homepage:
    • Creating a Homepage component to display the most recent jobs.
    • Fetching the most recent jobs from the database using prisma.job.findMany() with the take option to limit the number of results.

Conclusion

  • The video provides a comprehensive guide to using Prisma for building full-stack applications with Next.js.
  • It covers the fundamentals of Prisma, including schema definition, migrations, seeding, and CRUD operations.
  • It demonstrates how to integrate Prisma with NextAuth.js for authentication.
  • It provides a practical example of building a job posting website with features like browsing jobs, posting jobs, applying for jobs, and viewing the dashboard.
  • The video emphasizes the importance of type safety, performance, and developer experience when using Prisma.

AI summaries can miss context or contain errors. Check important details against the original video.

Go a little deeper.

Have a question about this video? Load its transcript to open the video chat.