\section{Prisma ORM}

\begin{frame}{Mi az a Prisma?}
  \begin{block}{Prisma}
    Modern ORM (Object-Relational Mapping) Node.js és TypeScript környezethez
  \end{block}
  
  \begin{block}{Főbb jellemzők}
    \begin{itemize}
      \item Típusbiztos adatbázis kliens
      \item Deklaratív séma definíció
      \item Automatikus migráció kezelés
      \item Intuitív API CRUD műveletekhez
      \item Támogatott adatbázisok: PostgreSQL, MySQL, SQLite, MongoDB, stb.
    \end{itemize}
  \end{block}
\end{frame}

\begin{frame}[fragile]{Prisma telepítése}
  \begin{block}{NPM telepítés}
    \begin{lstlisting}[language=bash]
# Prisma CLI telepítése dev dependencyként
npm install prisma --save-dev

# Prisma Client telepítése
npm install @prisma/client

# Prisma inicializálása
npx prisma init
    \end{lstlisting}
  \end{block}
  
  \begin{block}{Létrejövő fájlok}
    \begin{itemize}
      \item \texttt{prisma/schema.prisma} - Adatbázis séma
      \item \texttt{.env} - Környezeti változók (pl. DATABASE\_URL)
    \end{itemize}
  \end{block}
\end{frame}

\begin{frame}[fragile]{Prisma Schema alapok}
  \begin{block}{schema.prisma}
    \begin{lstlisting}[language=JavaScript]
generator client {
  provider = "prisma-client-js"
}
datasource db {
  provider = "postgresql"
  url      = env("DATABASE_URL")
}
model User {
  id        Int      @id @default(autoincrement())
  email     String   @unique
  name      String?
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt
}
    \end{lstlisting}
  \end{block}
\end{frame}

\begin{frame}[fragile]{Prisma migrációk}
  \begin{block}{Adatbázis migráció létrehozása és futtatása}
    \begin{lstlisting}[language=bash]
# Migráció létrehozása
npx prisma migrate dev --name init

# Prisma Client újragenerálása
npx prisma generate

# Adatbázis vizualizáció
npx prisma studio
    \end{lstlisting}
  \end{block}
\end{frame}

\begin{frame}[fragile]{Prisma Client inicializálása}
  \begin{block}{prisma.js}
    \begin{lstlisting}[language=JavaScript]
const { PrismaClient } = require('@prisma/client');

const prisma = new PrismaClient();

module.exports = prisma;
    \end{lstlisting}
  \end{block}
  
  \begin{alertblock}{Singleton pattern}
    Érdemes egyetlen Prisma Client példányt használni az alkalmazásban.
  \end{alertblock}
\end{frame}

\begin{frame}[fragile]{Create - Létrehozás}
  \begin{block}{Egy rekord létrehozása}
    \begin{lstlisting}[language=JavaScript]
const prisma = require('./prisma');

async function createUser() {
  const user = await prisma.user.create({
    data: {
      email: 'john@example.com',
      name: 'John Doe'
    }
  });
  
  console.log(user);
  // { id: 1, email: 'john@example.com', name: 'John Doe', ... }
}
    \end{lstlisting}
  \end{block}
\end{frame}

\begin{frame}[fragile]{Create - Több rekord}
  \begin{block}{createMany használata}
    \begin{lstlisting}[language=JavaScript]
async function createManyUsers() {
  const users = await prisma.user.createMany({
    data: [
      { email: 'alice@example.com', name: 'Alice' },
      { email: 'bob@example.com', name: 'Bob' },
      { email: 'charlie@example.com', name: 'Charlie' }
    ]
  });
  
  console.log(`${users.count} felhasználó létrehozva`);
}
    \end{lstlisting}
  \end{block}
\end{frame}

\begin{frame}[fragile]{Read - Összes rekord}
  \begin{block}{findMany használata}
    \begin{lstlisting}[language=JavaScript]
async function getAllUsers() {
  const users = await prisma.user.findMany();
  console.log(users);
}

// Rendezéssel
async function getUsersSorted() {
  const users = await prisma.user.findMany({
    orderBy: {
      name: 'asc'
    }
  });
}
    \end{lstlisting}
  \end{block}
\end{frame}

\begin{frame}[fragile]{Read - Egy rekord}
  \begin{block}{findUnique és findFirst}
    \begin{lstlisting}[language=JavaScript]
// Egyedi mező alapján (pl. id, email)
async function getUserById(id) {
  const user = await prisma.user.findUnique({
    where: { id: id }
  });
  return user;
}
// Első találat
async function getUserByName(name) {
  const user = await prisma.user.findFirst({
    where: { name: name }
  });
  return user;
}
    \end{lstlisting}
  \end{block}
\end{frame}

\begin{frame}[fragile]{Read - Szűrés}
  \begin{block}{Where feltételek}
    \begin{lstlisting}[language=JavaScript]
async function filterUsers() {
  const users = await prisma.user.findMany({
    where: {
      email: {
        contains: '@example.com'
      },
      name: {
        startsWith: 'J'
      }
    }
  });
  return users;
}
    \end{lstlisting}
  \end{block}
\end{frame}

\begin{frame}[fragile]{Read - Mezők kiválasztása}
  \begin{block}{Select használata}
    \begin{lstlisting}[language=JavaScript]
async function getUserEmails() {
  const users = await prisma.user.findMany({
    select: {
      id: true,
      email: true,
      name: true
    }
  });
  return users;
  // [{ id: 1, email: '...', name: '...' }, ...]
}
    \end{lstlisting}
  \end{block}
\end{frame}

\begin{frame}[fragile]{Update - Módosítás}
  \begin{block}{Egy rekord frissítése}
    \begin{lstlisting}[language=JavaScript]
async function updateUser(id) {
  const user = await prisma.user.update({
    where: { id: id },
    data: {
      name: 'Jane Doe',
      email: 'jane@example.com'
    }
  });
  return user;
}
    \end{lstlisting}
  \end{block}
\end{frame}

\begin{frame}[fragile]{Update - Több rekord}
  \begin{block}{updateMany használata}
    \begin{lstlisting}[language=JavaScript]
async function updateManyUsers() {
  const result = await prisma.user.updateMany({
    where: {
      email: {
        contains: '@old-domain.com'
      }
    },
    data: {
      email: 'updated@new-domain.com'
    }
  });
  
  console.log(`${result.count} rekord frissítve`);
}
    \end{lstlisting}
  \end{block}
\end{frame}

\begin{frame}[fragile]{Delete - Törlés}
  \begin{block}{Egy rekord törlése}
    \begin{lstlisting}[language=JavaScript]
async function deleteUser(id) {
  const user = await prisma.user.delete({
    where: { id: id }
  });
  return user;
}
    \end{lstlisting}
  \end{block}
\end{frame}

\begin{frame}[fragile]{Delete - Több rekord}
  \begin{block}{deleteMany használata}
    \begin{lstlisting}[language=JavaScript]
async function deleteInactiveUsers() {
  const result = await prisma.user.deleteMany({
    where: {
      createdAt: {
        lt: new Date('2020-01-01')
      }
    }
  });
  
  console.log(`${result.count} felhasználó törölve`);
}
    \end{lstlisting}
  \end{block}
\end{frame}

\begin{frame}[fragile]{Relációk - Schema}
  \begin{block}{Egy-a-többhöz kapcsolat}
    \begin{lstlisting}[language=JavaScript]
model User {
  id    Int     @id @default(autoincrement())
  name  String
  posts Post[]
}

model Post {
  id       Int    @id @default(autoincrement())
  title    String
  content  String?
  authorId Int
  author   User   @relation(fields: [authorId], 
                            references: [id])
}
    \end{lstlisting}
  \end{block}
\end{frame}

\begin{frame}[fragile]{Relációk - Include}
  \begin{block}{Kapcsolt adatok lekérdezése}
    \begin{lstlisting}[language=JavaScript]
async function getUserWithPosts(userId) {
  const user = await prisma.user.findUnique({
    where: { id: userId },
    include: {
      posts: true
    }
  });
  
  console.log(user);
  // { id: 1, name: 'John', posts: [...] }
}
    \end{lstlisting}
  \end{block}
\end{frame}

\begin{frame}[fragile]{Relációk - Nested Write}
  \begin{block}{Kapcsolt rekordok létrehozása}
    \begin{lstlisting}[language=JavaScript]
async function createUserWithPosts() {
  const user = await prisma.user.create({
    data: {
      name: 'John Doe',
      email: 'john@example.com',
      posts: {
        create: [
          { title: 'First Post', content: 'Hello!' },
          { title: 'Second Post', content: 'World!' }
        ]
      }
    }
  });
}
    \end{lstlisting}
  \end{block}
\end{frame}

\begin{frame}[fragile]{Tranzakciók}
  \begin{block}{Több művelet egy tranzakcióban}
    \begin{lstlisting}[language=JavaScript]
async function transferPosts(fromUserId, toUserId) {
  const result = await prisma.$transaction([
    prisma.post.updateMany({
      where: { authorId: fromUserId },
      data: { authorId: toUserId }
    }),
    prisma.user.update({
      where: { id: fromUserId },
      data: { name: 'Archived User' }
    })
  ]);
  
  return result;
}
    \end{lstlisting}
  \end{block}
\end{frame}

\begin{frame}[fragile]{Express integráció példa}
  \begin{block}{REST API endpoint Prisma-val}
    \begin{lstlisting}[language=JavaScript]
const express = require('express');
const prisma = require('./prisma');
const app = express();
app.use(express.json());
app.get('/users', async (req, res) => {
  const users = await prisma.user.findMany();
  res.json(users);
});
app.post('/users', async (req, res) => {
  const user = await prisma.user.create({
    data: req.body
  });
  res.json(user);
});
    \end{lstlisting}
  \end{block}
\end{frame}

\begin{frame}[fragile]{Hibakezelés}
  \begin{block}{Try-catch használata}
    \begin{lstlisting}[language=JavaScript]
async function safeCreateUser(data) {
  try {
    const user = await prisma.user.create({
      data: data
    });
    return { success: true, user };
  } catch (error) {
    if (error.code === 'P2002') {
      return { success: false, 
               error: 'Email már létezik' };
    }
    return { success: false, error: error.message };
  }
}
    \end{lstlisting}
  \end{block}
\end{frame}

\begin{frame}{Prisma előnyei}
  \begin{block}{Miért használjuk?}
    \begin{itemize}
      \item \textbf{Típusbiztonság} - Auto-complete és típus ellenőrzés
      \item \textbf{Egyszerű API} - Intuitív, könnyen tanulható
      \item \textbf{Migráció kezelés} - Automatikus séma szinkronizáció
      \item \textbf{Teljesítmény} - Optimalizált query-k
      \item \textbf{Prisma Studio} - Vizuális adatbázis böngésző
      \item \textbf{Jó dokumentáció} - Részletes guide-ok és példák
    \end{itemize}
  \end{block}
\end{frame}
