Back to notes
mastery-backend-nestjs
Featured

NestJS with Database: Prisma Integration & Docker Compose

สูตรสำเร็จเชื่อมต่อ Database: ตั้งค่า Prisma ORM ใน NestJS, การทำ Migration, และรัน Postgres ด้วย Docker Compose

January 29, 20262 min read readNNexis by Seereen

🛑 1. The Problem First: "สงคราม SQL ในสตริง" (Query Hell)

ลองนึกถึงวันที่คุณต้องเขียน SQL ดิบๆ ในโค้ด Backend:

HLJS TYPESCRIPT
// ❌ Naive Approach: SQL ในสตริง ไร้ Type Safety และดิ้นรนกับการจัดการ Connection
const query = "SELECT * FROM users WHERE id = " + userId; // 🌋 ระเบิดแน่ถ้าเจอ SQL Injection!
const rows = await db.execute(query);
// แล้ว 'rows' มีฟิลด์อะไรบ้าง? ต้องไปเปิด Schema ดู สลับไปมาจนตาลาย

ปัญหา: การเขียน SQL ดิบหรือใช้ ORM รุ่นเก่าทำให้คุณเสียเวลาอย่างมากกับการ "เดา" ว่าข้อมูลที่ได้กลับมาหน้าตาเป็นอย่างไร และเมื่อต้องแก้ Database Schema ทีหนึ่ง คุณต้องไล่หาทุุกจุดในโค้ดว่ามีตรงไหนพังบ้าง นี่คือฝันร้ายของการ Scale ระบบครับ


💡 2. Real-Life Analogy: นักแปลภาษาอัจฉริยะ (The Fluent Translator)

  • Database (Postgres): เหมือน "ห้องสมุดขนาดใหญ่". ข้อมูลถูกเก็บไว้อย่างเป็นระเบียบ แต่คุยคนละภาษากับแอปของคุณ (คุยภาษา SQL)
  • Docker Compose: เหมือน "ตู้คอนเทนเนอร์สำเร็จรูป". คุณไม่ต้องสร้างห้องสมุดเอง แค่สั่ง "กางตู้" (docker-compose up) คุณก็ได้ห้องสมุดสภาพดีพร้อมใช้งานทันที ไม่รกพื้นบ้าน
  • Prisma (ORM): เหมือน "เครื่องแปลภาษาอัจฉริยะ". มันมองเห็นหนังสือทุุกเล่มในห้องสมุด แล้วสรุปออกมาเป็นเมนูภาษาบ้านคุณ (TypeScript) ที่กดเลือกฟิลด์ได้เป๊ะๆ (Auto-completion) และถ้าห้องสมุดเปลี่ยนป้ายชื่อ เครื่องนี้จะเตือนคุณทันทีว่า "เมนูเดิมใช้ไม่ได้แล้วนะ!"

🚀 3. Execution Journey: มหากาพย์การสร้างฐานราก

เราจะสร้างระบบที่ "แก้ไขง่าย ตายยาก" ด้วย 3 ขั้นตอนระดับ Senior

🛠 Step-by-step:

  1. Infra with Docker: ใช้ Docker Compose เพื่อให้ทุกคนในทีมมี Database แบบเดียวกันเป๊ะๆ
  2. Schema Definition: กำหนดโมเดลใน prisma/schema.prisma เพื่อให้เป็น Single Source of Truth
  3. NestJS Service: สร้าง PrismaService เป็นกองกลาง (Singleton) เพื่อให้ทุุกโมเดลหยิบไปใช้ได้ง่ายๆ
HLJS TYPESCRIPT
// ✅ Best Practice: สร้างกองกลาง Prisma
@Injectable()
export class PrismaService extends PrismaClient implements OnModuleInit {
  async onModuleInit() {
    await this.$connect(); // 🛠 เชื่อมต่อทันทีเมื่อ Start แอป
  }
}

🪤 4. The Junior Trap: โรค "Hardcode DB URL"

จูเนียร์มักจะใส่ความลับไว้ในโค้ดโดยไม่รู้ตัว:

HLJS TYPESCRIPT
// ❌ Junior Trap: ความลับที่เปิดเผย
const dbUrl = "postgresql://user:password@localhost:5432/mydb";
// 🌋 พัง! เมื่อคุณ Push ขึ้น GitHub หรือเปลี่ยนเป็น Server จริง
// ระบบจะล่มเพราะ URL ไม่ตรงกัน และ Hacker จะยิ้มกริ่มกับ Password ของคุณ

ระวัง: ข้อมูลความลับห้ามอยู่ในโค้ดเด็ดขาด! ✅ การแก้ไข: ใช้ ConfigModule ของ NestJS เพื่อโหลดค่าจาก .env และใช้ ConfigService ในการดึงค่ามาใช้งานอย่างปลอดภัย


⚖️ 5. The Why Matrix: Prisma vs TypeORM

หัวข้อTypeORM (แบบคลาสสิก)Prisma (ยุคใหม่)
Type Safety⚡⚡ ดี (อิงตาม Class)⚡⚡⚡ เทพ (อิงตาม Database จริง)
Developer Experienceปานกลาง (ต้องเขียน Decorator เยอะ)🚀 สูงมาก (Auto-generated Client)
Migration🐢 ค่อนข้างวุ่นวาย⚡⚡ ง่ายและแม่นยำมาก
ประสิทธิภาพสูง (แต่คุมยาก)สูง (เพราะมี Rust Engine อยู่ข้างหลัง)

🎓 6. Senior Mindset Summary

การเป็น Senior คือการมองว่า "Database ไม่ใช่แค่ที่เก็บของ แต่คือหัวใจของความถูกต้อง (Data Integrity)". การใช้ Prisma ร่วมกับ NestJS ไม่ใช่แค่เรื่องความเท่ แต่คือการสร้าง "สัญญา" (Contract) ระหว่าง Code และ Data ให้แข็งแรงที่สุดเท่าที่จะเป็นไปได้ครับ!

Share this note

© 2026 My Notes by Seereen