Définition
Un ORM (Object-Relational Mapping) est une technique de programmation qui cree un "pont" entre les objets d'un langage de programmation et les tables d'une base de données relationnelle. L'ORM traduit automatiquement les opérations sur les objets en requêtes SQL.
Au lieu d'écrire du SQL brut, vous manipulez des objets dans votre langage favori, et l'ORM genere le SQL correspondant.
Pourquoi utiliser un ORM ?
Avantages
- Productivité : moins de code répétitif, auto-completion
- Type safety : détection d'erreurs au compilé time (TypeScript, Java)
- Portabilité : changer de SGBD sans reecrire les requêtes
- Migrations : versionner le schéma de la base de données
- Protection : prévention automatique des injections SQL
- Relations : gestion simplifiée des jointures et associations
Inconvénients
- Performance : requêtes N+1 si mal utilise
- Abstraction fuyante : certaines requêtes complexes nécessitent du SQL brut
- Courbe d'apprentissage : chaque ORM à sa propre API
- Debug : plus difficile de comprendre le SQL genere
ORM populaires par langage
| Langage | ORM | Type |
|---|---|---|
| TypeScript/JS | Drizzle | Type-safe, SQL-like |
| TypeScript/JS | Prisma | Schema-first, type-safe |
| TypeScript/JS | TypeORM | Decorator-based |
| Python | SQLAlchemy | Full-featured, flexible |
| Python | Django ORM | Integre à Django |
| Java | Hibernate/JPA | Standard enterprise |
| PHP | Eloquent | Integre à Laravel |
| C# | Entity Framework | Integre a .NET |
| Go | GORM | Struct-based |
| Ruby | Active Record | Convention over config |
Exemple comparatif : Drizzle vs SQL brut
// Drizzle ORM (type-safe)
const users = await db.select()
.from(usersTable)
.where(eq(usersTable.active, true))
.leftJoin(ordersTable, eq(usersTable.id, ordersTable.userId))
.orderBy(desc(usersTable.createdAt))
.limit(20);
// SQL equivalent
const users = await sql\`
SELECT * FROM users u
LEFT JOIN orders o ON u.id = o.user_id
WHERE u.active = true
ORDER BY u.created_at DESC
LIMIT 20
\`;
Le problème N+1
Le piège classique des ORM : charger une liste d'objets, puis charger les relations une par une.
// MAUVAIS : N+1 requetes (1 pour les users + N pour les commandes)
const users = await db.select().from(usersTable);
for (const user of users) {
user.orders = await db.select().from(ordersTable).where(eq(ordersTable.userId, user.id));
}
// BON : 1 seule requete avec jointure ou eager loading
const users = await db.select().from(usersTable)
.leftJoin(ordersTable, eq(usersTable.id, ordersTable.userId));
Tendance actuelle
La tendance en 2026 est aux ORM "type-safe" et "SQL-like" comme Drizzle qui offrent le meilleur des deux mondes : la sécurité des types et la clarte du SQL.