We use tracking cookies to understand how you use the product and help us improve it. For more information on how we store cookies, read our  privacy policy.

Usage & Integration

Learn how to use Prisma Client in your Plainform application.

This page shows practical examples of using Prisma Client in Plainform for database queries and mutations.

Prisma Client Setup

Plainform uses a singleton pattern to prevent connection exhaustion:

lib/prisma/prisma.ts
import { PrismaClient } from '@prisma/client';

declare global {
  var prisma: PrismaClient | undefined;
}

let prisma: PrismaClient;

if (process.env.NODE_ENV === 'production') {
  prisma = new PrismaClient();
} else {
  if (!global.prisma) {
    global.prisma = new PrismaClient();
  }
  prisma = global.prisma;
}

export { prisma };

Why singleton? Prevents multiple Prisma instances in development and avoids connection pool exhaustion.

Basic CRUD Operations

Create and Read

app/api/events/route.ts
import { prisma } from '@/lib/prisma/prisma';
import { NextResponse } from 'next/server';

export async function POST(req: Request) {
  const { text, type, slug, timestamp } = await req.json();

  const event = await prisma.event.create({
    data: { text, type, slug, timestamp: BigInt(timestamp) }
  });

  return NextResponse.json({ event });
}

export async function GET() {
  // Find single record
  const event = await prisma.event.findFirst({
    orderBy: { timestamp: 'desc' }
  });

  // Find many records
  const events = await prisma.event.findMany({
    where: { type: 'post' },
    orderBy: { timestamp: 'desc' },
    take: 10
  });

  return NextResponse.json({ event, events });
}

Update and Delete

app/api/events/route.ts
export async function PATCH(req: Request) {
  const { id, text } = await req.json();

  const event = await prisma.event.update({
    where: { id },
    data: { text }
  });

  return NextResponse.json({ event });
}

export async function DELETE(req: Request) {
  const { searchParams } = new URL(req.url);
  const type = searchParams.get('type');

  await prisma.event.deleteMany({ where: { type } });

  return NextResponse.json({ message: 'Deleted' });
}

Filtering and Pagination

Example queries
// Where clauses
const posts = await prisma.event.findMany({
  where: {
    type: 'post',
    timestamp: { gte: BigInt(Date.now() - 86400000) }
  }
});

// OR conditions
const events = await prisma.event.findMany({
  where: {
    OR: [{ type: 'post' }, { type: 'update' }]
  }
});

// Pagination
const page = 1;
const limit = 20;

const events = await prisma.event.findMany({
  skip: (page - 1) * limit,
  take: limit,
  orderBy: { timestamp: 'desc' }
});

Relationships

Including related data
// Assuming Post and Comment models
const posts = await prisma.post.findMany({
  include: {
    author: true,
    comments: {
      take: 5,
      orderBy: { createdAt: 'desc' }
    }
  }
});

// Create with relationships
const post = await prisma.post.create({
  data: {
    title: 'My Post',
    author: { connect: { id: userId } },
    comments: {
      create: [{ text: 'First comment', authorId: userId }]
    }
  },
  include: { comments: true }
});

Server Components

Use Prisma directly in Server Components:

app/dashboard/page.tsx
import { prisma } from '@/lib/prisma/prisma';

export default async function DashboardPage() {
  const events = await prisma.event.findMany({
    orderBy: { timestamp: 'desc' },
    take: 10
  });

  return (
    <div>
      <h1>Recent Events</h1>
      {events.map(event => (
        <div key={event.id}>{event.text}</div>
      ))}
    </div>
  );
}

Server Components can query the database directly without API routes, reducing latency.

Transactions

Use transactions for operations that must succeed or fail together:

Example transaction
const result = await prisma.$transaction([
  prisma.event.deleteMany({ where: { type: 'old' } }),
  prisma.event.create({
    data: { type: 'new', text: 'New event', slug: 'new', timestamp: BigInt(Date.now()) }
  })
]);

BigInt Serialization

PostgreSQL BIGINT fields require special handling for JSON:

lib/utils.ts
export function serializeBigInt(obj: any): any {
  return JSON.parse(
    JSON.stringify(obj, (key, value) =>
      typeof value === 'bigint' ? value.toString() : value
    )
  );
}
app/api/events/route.ts
import { serializeBigInt } from '@/lib/utils';

export async function GET() {
  const event = await prisma.event.findFirst();
  return NextResponse.json({ event: serializeBigInt(event) });
}

Why needed? JavaScript's JSON.stringify() can't serialize BigInt and throws an error.

Error Handling

Handle Prisma errors gracefully:

app/api/events/route.ts
import { Prisma } from '@prisma/client';

export async function POST(req: Request) {
  try {
    const data = await req.json();
    const event = await prisma.event.create({ data });
    return NextResponse.json({ event });
  } catch (error) {
    if (error instanceof Prisma.PrismaClientKnownRequestError) {
      if (error.code === 'P2002') {
        return NextResponse.json(
          { error: 'Record already exists' },
          { status: 409 }
        );
      }
    }
    
    return NextResponse.json(
      { error: 'Database operation failed' },
      { status: 500 }
    );
  }
}

Next Steps

How is this guide ?

Last updated on