Prisma ORM patterns including Prisma Client usage, queries, mutations, relations, transactions, and schema management. Use when working with Prisma database operations or schema definitions.
Complete patterns for using Prisma ORM effectively, including query optimization, transaction handling, and the repository pattern for clean data access.
import { PrismaService } from '@project-lifecycle-portal/database';
// Always use PrismaService.main
if (!PrismaService.isAvailable) {
throw new Error('Prisma client not initialized');
}
// Find one
const user = await PrismaService.main.user.findUnique({
where: { id: userId },
});
// Find many with filters
const users = await PrismaService.main.user.findMany({
where: { isActive: true },
orderBy: { createdAt: 'desc' },
take: 10,
});
// Create
const newUser = await PrismaService.main.user.create({
data: {
email: 'user@example.com',
name: 'John Doe',
},
});
// Update
const updated = await PrismaService.main.user.update({
where: { id: userId },
data: { name: 'Jane Doe' },
});
// Delete
await PrismaService.main.user.delete({
where: { id: userId },
});
// Multiple conditions
const users = await PrismaService.main.user.findMany({
where: {
email: { contains: '@example.com' },
isActive: true,
createdAt: { gte: new Date('2024-01-01') },
},
});
// AND/OR conditions
const posts = await PrismaService.main.post.findMany({
where: {
AND: [
{ published: true },
{ author: { isActive: true } },
],
OR: [
{ title: { contains: 'prisma' } },
{ content: { contains: 'prisma' } },
],
},
});
✅ Use repositories when:
❌ Skip repositories for:
import { PrismaService } from '@project-lifecycle-portal/database';
import type { User, Prisma } from '@prisma/client';
export class UserRepository {
async findById(id: string): Promise<User | null> {
return PrismaService.main.user.findUnique({
where: { id },
include: { profile: true },
});
}
async findByEmail(email: string): Promise<User | null> {
return PrismaService.main.user.findUnique({
where: { email },
});
}
async findActive(): Promise<User[]> {
return PrismaService.main.user.findMany({
where: { isActive: true },
orderBy: { createdAt: 'desc' },
});
}
async create(data: Prisma.UserCreateInput): Promise<User> {
return PrismaService.main.user.create({ data });
}
async update(id: string, data: Prisma.UserUpdateInput): Promise<User> {
return PrismaService.main.user.update({ where: { id }, data });
}
async delete(id: string): Promise<void> {
await PrismaService.main.user.delete({ where: { id } });
}
}
export class UserService {
private userRepository: UserRepository;
constructor() {
this.userRepository = new UserRepository();
}
async getById(id: string): Promise<User> {
const user = await this.userRepository.findById(id);
if (!user) {
throw new Error('User not found');
}
return user;
}
}
const result = await PrismaService.main.$transaction(async (tx) => {
const user = await tx.user.create({
data: { email: 'user@example.com', name: 'John' },
});
const profile = await tx.userProfile.create({
data: { userId: user.id, bio: 'Developer' },
});
return { user, profile };
});
const result = await PrismaService.main.$transaction(
async (tx) => {
const user = await tx.user.findUnique({ where: { id: userId } });
if (!user) throw new Error('User not found');
const updated = await tx.user.update({
where: { id: userId },
data: { lastLogin: new Date() },
});
await tx.auditLog.create({
data: { userId, action: 'LOGIN', timestamp: new Date() },
});
return updated;
},
{
maxWait: 5000, // Wait max 5s to start
timeout: 10000, // Timeout after 10s
}
);
// ❌ Fetches all fields
const users = await PrismaService.main.user.findMany();
// ✅ Only fetch needed fields
const users = await PrismaService.main.user.findMany({
select: {
id: true,
email: true,
name: true,
},
});
// ✅ Select with relations
const users = await PrismaService.main.user.findMany({
select: {
id: true,
email: true,
profile: {
select: { firstName: true, lastName: true },
},
},
});
// ❌ Excessive includes
const user = await PrismaService.main.user.findUnique({
where: { id },
include: {
posts: { include: { comments: true } },
workflows: { include: { steps: { include: { actions: true } } } },
},
});
// ✅ Only include what you need
const user = await PrismaService.main.user.findUnique({
where: { id },
include: { profile: true },
});
// ❌ N+1 Query Problem
const users = await PrismaService.main.user.findMany(); // 1 query
for (const user of users) {
// N additional queries
const profile = await PrismaService.main.userProfile.findUnique({
where: { userId: user.id },
});
}
// ✅ Single query with include
const users = await PrismaService.main.user.findMany({
include: { profile: true },
});
for (const user of users) {
console.log(user.profile.bio);
}
// ✅ Batch query
const users = await PrismaService.main.user.findMany();
const userIds = users.map(u => u.id);
const profiles = await PrismaService.main.userProfile.findMany({
where: { userId: { in: userIds } },
});
const profileMap = new Map(profiles.map(p => [p.userId, p]));
// Get user with posts
const user = await PrismaService.main.user.findUnique({
where: { id: userId },
include: {
posts: {
where: { published: true },
orderBy: { createdAt: 'desc' },
take: 10,
},
},
});
// Create user with profile
const user = await PrismaService.main.user.create({
data: {
email: 'user@example.com',
name: 'John Doe',
profile: {
create: {
bio: 'Developer',
avatar: 'avatar.jpg',
},
},
},
include: { profile: true },
});
// Update with nested updates
const user = await PrismaService.main.user.update({
where: { id: userId },
data: {
name: 'Jane Doe',
profile: {
update: { bio: 'Senior developer' },
},
},
});
import { Prisma } from '@prisma/client';
try {
await PrismaService.main.user.create({
data: { email: 'user@example.com' },
});
} catch (error) {
if (error instanceof Prisma.PrismaClientKnownRequestError) {
// P2002: Unique constraint violation
if (error.code === 'P2002') {
throw new ConflictError('Email already exists');
}
// P2003: Foreign key constraint failed
if (error.code === 'P2003') {
throw new ValidationError('Invalid reference');
}
// P2025: Record not found
if (error.code === 'P2025') {
throw new NotFoundError('Record not found');
}
}
Sentry.captureException(error);
throw error;
}
| Code | Meaning |
|---|---|
| P2002 | Unique constraint violation |
| P2003 | Foreign key constraint failed |
| P2025 | Record not found |
| P2014 | Relation violation |
// Count
const count = await PrismaService.main.user.count({
where: { isActive: true },
});
// Aggregate
const stats = await PrismaService.main.post.aggregate({
_count: true,
_avg: { views: true },
_sum: { likes: true },
where: { published: true },
});
// Group by
const postsByAuthor = await PrismaService.main.post.groupBy({
by: ['authorId'],
_count: { id: true },
});
// Update if exists, create if not
const user = await PrismaService.main.user.upsert({
where: { email: 'user@example.com' },
update: { lastLogin: new Date() },
create: {
email: 'user@example.com',
name: 'John Doe',
},
});
import type { User, Prisma } from '@prisma/client';
// Create input type
const createUser = async (data: Prisma.UserCreateInput): Promise<User> => {
return PrismaService.main.user.create({ data });
};
// Include type
type UserWithProfile = Prisma.UserGetPayload<{
include: { profile: true };
}>;
const user: UserWithProfile = await PrismaService.main.user.findUnique({
where: { id },
include: { profile: true },
});
Related Skills: