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

By PedroTech

TechnologyStartupEducation
Share:

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: 'alice@example.com' },
          { name: 'Bob', email: 'bob@example.com' },
        ],
      });
    }
    
  • 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: 'pedro@example.com' },
          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: 'liam@example.com' },
        });
        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.

Chat with this Video

AI-Powered

Hi! I can answer questions about this video "Prisma ORM Full Course 2025 | Become a Prisma Pro in 2.5 Hours". What would you like to know?

Chat is based on the transcript of this video and may not be 100% accurate.

Related Videos

Ready to summarize another video?

Summarize YouTube Video