Mikro-ORM مع TypeScript: دليل شامل مع أمثلة
1. ما هي Mikro-ORM ولماذا تحتاجها؟
Mikro-ORM هي مكتبة حديثة للربط بين الكائنات وقواعد البيانات (ORM) مخصصة لـ TypeScript و JavaScript (Node.js)، وتطبق أنماط Identity Map و Unit of Work. على عكس ORMs التقليدية مثل TypeORM أو Sequelize، فإن Mikro-ORM مستوحاة من Doctrine (PHP) و Hibernate (Java) وتوفر إدارة أكثر قابلية للتنبؤ بحالة الكيانات ومزامنتها مع قاعدة البيانات.
لماذا تحتاجها؟ في تطبيقات الويب النموذجية، غالبًا ما يواجه المطورون مشكلة البيانات "القذرة"، حيث يتم تحميل نفس السجل مرتين في أماكن مختلفة من الكود، مما يؤدي إلى تعارضات عند الحفظ. تحل Mikro-ORM هذه المشكلة باستخدام Identity Map: لكل مفتاح أساسي، يوجد نسخة واحدة فقط من الكيان ضمن سياق واحد (EntityManager). وهذا يضمن أنك تعمل دائمًا على أحدث إصدار من الكائن، ويتم تتبع جميع التغييرات تلقائيًا.
تدعم المكتبة العديد من أنظمة إدارة قواعد البيانات (PostgreSQL, MySQL, SQLite, MongoDB, MariaDB) وتوفر أدوات قوية: الترحيلات (migrations)، دعم مدمج للمعاملات (transactions)، العمليات المتتالية (cascading)، تحميل العلاقات (eager/lazy)، مدقق مخطط مدمج، ومنشئ كيانات من قاعدة بيانات موجودة. تعتبر Mikro-ORM مثالية لنماذج المجال المعقدة وهندسة الخدمات المصغرة حيث تكون اتساقية البيانات مهمة.
2. التثبيت
لتثبيت Mikro-ORM ومشغل قاعدة البيانات المطلوب، قم بتنفيذ الأمر عبر npm (أو yarn/pnpm):
# تثبيت نواة المكتبة
npm install @mikro-orm/core
# تثبيت مشغل قاعدة البيانات الخاصة بك (اختر واحدًا):
npm install @mikro-orm/sqlite # SQLite
npm install @mikro-orm/postgresql # PostgreSQL
npm install @mikro-orm/mysql # MySQL / MariaDB
npm install @mikro-orm/mongodb # MongoDB
# إضافي: CLI للترحيلات وإنشاء المخططات
npm install @mikro-orm/cli
npm install @mikro-orm/migrations # للترحيلات
يوصى أيضًا بتثبيت reflect-metadata لعمل الديكورات:
npm install reflect-metadata
أضف إلى tsconfig.json:
{
"compilerOptions": {
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"target": "ES2021",
"module": "commonjs"
}
}
3. بداية سريعة — مثال عملي بسيط
لننشئ تطبيقًا بسيطًا على SQLite مع كيان واحد User.
الخطوة 1. تعريف الكيان (entities/User.ts):
import { Entity, PrimaryKey, Property } from '@mikro-orm/core';
@Entity()
export class User {
@PrimaryKey()
id!: number;
@Property()
name!: string;
@Property()
email!: string;
@Property()
createdAt: Date = new Date();
}
الخطوة 2. إعداد Mikro-ORM (index.ts):
import 'reflect-metadata';
import { MikroORM } from '@mikro-orm/core';
import { SqliteDriver } from '@mikro-orm/sqlite';
import { User } from './entities/User';
async function main() {
const orm = await MikroORM.init({
entities: [User],
dbName: 'test.db',
driver: SqliteDriver,
debug: true, // تسجيل استعلامات SQL
});
// إنشاء المخطط (في وضع التطوير)
await orm.getSchemaGenerator().createSchema();
// الحصول على EntityManager
const em = orm.em.fork();
// إنشاء مستخدم
const user = em.create(User, {
name: 'أحمد',
email: 'ahmed@example.com',
});
await em.flush(); // حفظ في قاعدة البيانات
// قراءة المستخدم
const found = await em.findOne(User, { email: 'ahmed@example.com' });
console.log('تم العثور على:', found);
// تحديث
found!.name = 'محمد';