Prisma ORM: Ein Überblick über die moderne ORM-Lösung für TypeScript und Node.js
Von Caroline Labres am 22.01.2025
Datenbanken sind in vielen modernen Anwendungen nicht wegzudenken – doch SQL-Abfragen können schnell komplex und Datenbank-Migrationen können auf Dauer mühsam werden. Hier kommt Prisma ORM ins Spiel: Ein innovatives Tool, das die Arbeit mit Datenbanken erheblich vereinfacht. Prisma verbindet Typsicherheit, Automatisierung und Benutzerfreundlichkeit und bietet damit alles, was für eine effiziente Entwicklung benötigt wird. Dieser Beitrag soll nach einer kurzen theoretischen Einführung vor allem praktisch erklären wie Prisma ORM beispielhaft innerhalb eines NestJS-Projekts verwendet werden kann.
Was ist Prisma ORM?
Prisma ORM ist, wie der Name schon verrät, ein ORM (object-relational mapping), also eine Objektrelationale Abbildung für TypeScript und Node.js. ORMs abstrahieren die Komplexität der Datenbank, indem sie über Objekte eine Schnittstelle zum Holen, Erstellen, Bearbeiten und Löschen von Daten bieten. Es werden Modelle bzw. Klassen geschrieben, die den Tabellen in der Datenbank entsprechen. Prisma ORM verfolgt dabei allerdings einen schema-first Ansatz. Das bedeutet, dass es ein zentrales Schema-File gibt, auf dem alles basiert. Außerdem ist Prisma ORM open-source (bis auf Prisma Sudio – siehe nächster Abschnitt).
Bestandteile
Prisma besteht aus folgenden drei Teilen:
- Prisma Client
- Prisma Migrate
- Prisma Studio
Prisma Client
Der Prisma Client ist eine automatisch basierend auf dem Prisma-Schema generierte, typsichere API, mit der Datenbankabfragen durchgeführt werden können. Es muss also nicht manuell SQL geschrieben werden und durch die Typsicherheit werden Fehler frühzeitig vermieden. Dieser Bestandteil ist der Teil von Prisma ORM, der am häufigsten vorkommt, weshalb er oftmals auch nur Prisma genannt wird.
Prisma Migrate
Prisma Migrate ist ein Tool zum Verwalten von Datenbankschemas. In Form von Migrationen können leicht Änderungen an der Struktur der Datenbank vorgenommen werden. Dadurch können Code und Datenbank synchron gehalten werden.
Prisma Studio
Prisma Studio bietet einen grafische Benutzeroberfläche, um die Datenbank durchsuchen zu können und die Daten verwalten zu können. Auf diesen Teil wird in dem Blogartikel nicht genauer eingegangen.
Erste Schritte
Im folgenden Abschnitt wird nun erklärt wie Prisma ORM beispielhaft in einem NestJS Projekt installiert und verwendet werden kann.
1. Projekt aufsetzen
Zuerst muss NestJS CLI installiert und ein neues Projekt erstellt werden. Wenn ein bestehendes Projekt verwendet wird, kann dieser Schritt übersprungen werden
npm i -g @nestjs/cli
nest new prisma-test
Im Ordner des Projekts, muss nun Prisma CLI installiert und ein neues Prisma-Projekt initialisiert werden.
npm i prisma --save-dev
npx prisma init
Nun muss die Datenbankverbindung hergestellt werden. Dazu muss im .env File die richtige URL gesetzt (siehe dazu https://www.prisma.io/docs/orm/reference/connection-urls) und in der schema.prisma Datei der provider im datasource Block angepasst werden. Ich arbeite lokal mit XAMPP und einer MySQL Datenbank. Prisma ORM kann aber mit PostgreSQL, MySQL, MariaDB, SQLite, MongoDB, Supabase und vielen weiteren Datenbanken genutzt werden.
2. Tabellen erstellen
Um Tabellen zu erstellen, müssen zuerst Models im Prisma Schema erstellt werden. Das prisma.schema File könnte beispielsweise so aussehen:
model User {
id Int @id @default(autoincrement())
username String @unique
posts Post[]
}
model Post {
id Int @id @default(autoincrement())
title String
text String?
published Boolean? @default(false)
author User? @relation(fields: [authorId], references: [id])
authorId Int?
}
Zuerst wird der Name des Feldes definiert, dann der Typ (? für optional) angegeben und abschließend die Eigenschaften angeführt.
Hinweis zu VS Code:
Arbeitet man in VS Code, so empfiehlt es sich, die Extension “Prisma” von Prisma selbst herunterzuladen, um die Lesbarkeit des Schemas durch Syntax Highlighting zu verbessern.
Nachdem die Datei gespeichert wurde, können nun mittels Prisma Migrate die Migration Files erstellt werden, die dann unter prisma/migrations
zu finden sind.
npx prisma migrate dev --name init
3. Prisma Client installieren und verwenden
npm i @prisma/client
Mit der Installation wird auch schon prisma generate
ausgeführt. In der Zukunft muss nach jeder Änderung am Model dieser Befehl ausgeführt werden, um den Prisma Client up-to-date zu halten.
Nun erstellen wir ein Prisma Service (prisma.service.ts) im src
Ordner, welches wir dann in anderen Services verwenden können.
import { Injectable, OnModuleInit } from '@nestjs/common';
import { PrismaClient } from '@prisma/client';
@Injectable()
export class PrismaService extends PrismaClient implements OnModuleInit {
async onModuleInit() {
await this.$connect();
}
}
Um ein Module, ein Service und einen Controller in NestJS zu erstellen werden folgende Befehle benötigt:
nest g mo user
nest g s user
nest g co user
Dasselbe macht man für die Posts. Dann kann das User Service erweitert werden. Um das Prisma Service verwenden zu können, muss es im App Module und jedem weiteren wie z.B. User Module unter Providers hinzugefügt werden.
So könnte das User Service aussehen:
import { Injectable } from '@nestjs/common';
import { PrismaService } from '../prisma.service';
import { Prisma, User } from '@prisma/client';
@Injectable()
export class UserService {
constructor(private prisma: PrismaService) { }
async findUserById(
id: number,
): Promise<User | null> {
return this.prisma.user.findUnique({
where: { id },
});
}
async findAllUsers(): Promise<User[]> {
return this.prisma.user.findMany();
}
async createUser(data: Prisma.UserCreateInput): Promise<User> {
return this.prisma.user.create({
data,
});
}
async updateUser(params: {
id: number;
data: Prisma.UserUpdateInput;
}): Promise<User> {
const { id, data } = params;
return this.prisma.user.update({
where: { id },
data: data
});
}
async deleteUser(id: number): Promise<User> {
return this.prisma.user.delete({
where: { id }
});
}
}
Das Prisma Service (bzw. der Prisma Client) stellt einem die CRUD Methoden zur Verfügung und auch die Types können direkt von Prisma übernommen werden. Nach demselben Prinzp kann das Post Service erweitert werden.
Möchte man beim Laden eines Posts auch die Informationen des Autors bzw. der Autorin mitgeben, so kann include
oder select
verwendet werden.
async findPostById(
id: number,
): Promise<Post | null> {
return this.prisma.post.findUnique({
where: { id },
include: {
author: true
}
});
}
Es gibt unzählige Query Optionen, die verwendet werden können um nach bestimmten Daten zu suchen, sortieren, filtern etc. Siehe https://www.prisma.io/docs/orm/prisma-client/queries.
4. Endpoints definieren
In den Controllern definiert man dann seine Endpoints und ruft die Methoden des spezifischen Services auf.
import { Body, Controller, Get, Post } from '@nestjs/common';
import { UserService } from './user.service';
import { User } from '@prisma/client';
@Controller('user')
export class UserController {
constructor(
private readonly userService: UserService,
) { }
@Post()
async createUser(
@Body() userData: { username: string; },
): Promise<User> {
return this.userService.createUser(userData);
}
@Get()
async getAllUsers(): Promise<Array<User>> {
return this.userService.findAllUsers();
}
}
Da dies NestJS spezifisch ist und nichts direkt mit Prisma zu tun hat, wird darauf hier nicht näher eingegangen.
Mit npm run start:dev
kann die Applikation gestartet werden.
Fazit
Prisma ORM vereinfacht den Umgang mit der Datenbank erheblich und ist leicht zu erlernen. Im Vergleich zu anderen ORMs wie zum Beipsiel TypeORM werden die Models genau in einem File, dem Prisma Schema, definiert und alles andere wird basierend darauf generiert. Bei TypeORM hingegen definiert man zuerst die Entity-Klassen in mehreren Dateien und versieht die enthaltenen Properties mit Decoratorn, woraufhin TypeORM diese in Datenbank Informationen verwandelt. Bei Prisma ORM sind außerdem die automatisch generierten Types sehr praktisch. Und was dabei aber nie verloren geht, sind die Personalisierungsmöglichkeiten bei den Queries.
Quellen
https://www.prisma.io/docs/orm/overview/prisma-in-your-stack/is-prisma-an-orm
https://medium.com/@binayakgourishankar/getting-started-with-prisma-orm-89c2fcda5026
https://docs.nestjs.com/recipes/prisma
https://dev.to/afl_ext/prisma-vs-typeorm-description-and-comparison-4bob
https://www.prisma.io/docs/orm/overview/databases