Какво е ORM? Как приложенията общуват с базите данни, обяснено
ORM (object-relational mapper) е библиотека за код, която стои между приложението и релационната база данни. Вместо да пишат заявки на SQL, разработчиците работят с данните като с обикновени обекти в своя език за програмиране – db.booking.create(...) или Booking.find(...) – а ORM-ът превежда това в SQL, изпълнява го и връща резултатите обратно като обекти. Популярни примери са Prisma и Drizzle за TypeScript, SQLAlchemy за Python и Entity Framework Core за C#.
Защо ORM е важен, когато създаваш с ИИ
Когато ИИ инструмент за създаване на приложения добави база данни към вашето приложение, обикновено добавя и ORM, за да комуникира с нея. Няма да се налага да пишете код за ORM, но е полезно да знаете, че е там:
- Моделът на данните живее в кода. Файлът със схемата на ORM често е най-ясното описание на данните в приложението: кои таблици съществуват, какви полета има всяка и как са свързани. Четенето му е бърз начин да проверите дали ИИ е разбрал приложението ви.
- Промените в базата минават през миграции. Когато поискате „добави телефонен номер към клиентите“, ИИ обновява модела и създава миграция. Ако знаете това, ще разберете защо една промяна може да трябва да бъде приложена, преди да заработи на живо.
- Безопасност по подразбиране. ORM строи заявките по начин, който защитава от SQL инжекции – една от най-честите уязвимости в приложения, които сглобяват заявки на ръка.
- Капани за производителност. ORM-ът лесно може да изпълни стотици малки заявки там, където би стигнала една. Това е честа причина за бавни страници в приложения, създадени с ИИ.
Ежедневна аналогия
Представете си британски турист и японски търговец, които не говорят общ език и общуват чрез преводач.
Туристът (вашето приложение) казва: „Бих искал трите най-евтини чая, които имате.“ Преводачът (ORM-ът) превежда това на точен японски (SQL), предава го на търговеца (базата данни) и превежда отговора обратно на английски.
Туристът никога не научава японски и за повечето разговори това е наред. Но за сложно пазарлъкване може да е полезно да говори директно – затова повечето ORM позволяват на разработчиците да пишат суров SQL, когато е необходимо.
Как работи ORM
Базите данни като Postgres съхраняват данните в таблици от редове и колони и се четат със SQL. Езиците за програмиране работят с обекти: резервация с date, customer и status. ORM-ът съпоставя едното с другото:
| Страна на базата данни | Страна на ORM / кода |
|---|---|
Таблица bookings | Модел Booking |
| Ред | Един обект резервация |
Колона starts_at | Поле startsAt |
Външен ключ customer_id | Връзка booking.customer |
SELECT, INSERT, UPDATE, DELETE | Методите find, create, update, delete |
Тези четири операции са CRUD действията, на които се основават почти всички приложения.
Практически пример: резервации с Prisma
Ето опростена схема на Prisma за приложение за резервации в салон. Тя описва две таблици и как са свързани:
model Customer {
id Int @id @default(autoincrement())
name String
email String @unique
bookings Booking[]
}
model Booking {
id Int @id @default(autoincrement())
startsAt DateTime
service String
customer Customer @relation(fields: [customerId], references: [id])
customerId Int
}
С прости думи: клиентът има име, уникален имейл и много резервации; всяка резервация има начален час, услуга и принадлежи към един клиент.
Сега приложението иска „предстоящите резервации на Лена, най-близката първа“:
const bookings = await db.booking.findMany({
where: {
customer: { email: "lena@example.com" },
startsAt: { gte: new Date() },
},
orderBy: { startsAt: "asc" },
});
ORM-ът превръща това в SQL приблизително така, изпълнява го и връща списък с обекти резервации:
SELECT b.* FROM "Booking" b
JOIN "Customer" c ON c.id = b."customerId"
WHERE c.email = $1 AND b."startsAt" >= $2
ORDER BY b."startsAt" ASC;
$1 и $2 са placeholder-и: имейлът и датата се изпращат отделно от текста на заявката, и именно това предотвратява SQL инжекцията.
Миграции
Ако после поискате „нека клиентите добавят телефонен номер“, ИИ добавя phone String? към модела Customer (? означава, че полето е незадължително) и генерира миграция – малък SQL скрипт, например ALTER TABLE "Customer" ADD COLUMN "phone" TEXT;. Миграциите се запазват по ред, така че всяко копие на базата може да бъде приведено в същата структура, а историята на промените се пази.
Често срещани ORM-и по език
| Език | Често срещани ORM-и |
|---|---|
| TypeScript / JavaScript | Prisma, Drizzle, TypeORM, Sequelize |
| Python | SQLAlchemy, Django ORM, SQLModel |
| C# | Entity Framework Core |
| Java | Hibernate (често през Spring Data JPA) |
| Ruby | Active Record |
ORM-ите се различават по това колко скриват SQL. Prisma използва собствен език за схемите и собствен стил на заявки; Drizzle умишлено остава близо до формата на SQL, като същевременно запазва всичко типизирано. По-леките инструменти, наречени query builders, като Knex или Kysely за TypeScript, помагат да се строи SQL в кода, без да се съпоставят редовете с пълни обекти.
Ключови термини
| Термин | Значение |
|---|---|
| Модел | Описанието в кода на една таблица и нейните полета. |
| Схема | Пълното описание на всички таблици, полета и връзки. |
| Връзка | Свързване между модели, например резервация, която принадлежи на клиент. |
| Миграция | Версиран скрипт, който променя структурата на базата данни. |
| Query builder | По-лек инструмент за строене на SQL в кода, без пълно съпоставяне с обекти. |
| Проблем N+1 | Една заявка за списък, после по една допълнителна за всеки елемент – бавно при голям мащаб. |
| Суров SQL | SQL, написан на ръка, когато ORM-ът пречи. |
Често срещани заблуди
- „ORM е база данни.“ Не е. Той е преводач. Пак ви трябва база данни, например Postgres.
- „С ORM не е нужно да разбирате данните си.“ Зле проектираните таблици са също толкова проблемни през ORM. Добрият модел на данните е по-важен от инструмента.
- „ORM-ите винаги са бавни.“ Ежедневните заявки са наред. Бавността обикновено идва от шаблони като N+1 заявки или липсващи индекси, а те могат да се оправят.
- „ORM означава, че няма риск от SQL инжекция, никога.“ Стандартните методи на ORM са безопасни, но суров SQL, в който е вмъкнат въведен от потребителя текст, си остава опасен.
- „Редактирането на файла със схемата променя живата база.“ Само след като се създаде миграция и тя се приложи към тази база.
Какво да попитате вашия ИИ инструмент
- „Покажи ми схемата на базата данни и обясни всяка таблица и връзка с прости думи.“
- „Кой ORM използва този проект и къде са миграциите?“
- „Преди да променяш която и да е таблица, кажи дали съществуващите данни ще бъдат засегнати и никога не премахвай колона с данни, без да питаш.“
- „Провери най-бавните страници за N+1 заявки и добави индекси там, където списъците се филтрират или сортират.“
- „Увери се, че всяка заявка, която използва въведен от потребителя текст, минава през ORM или използва параметри – без SQL, сглобен от низове.“
ORM в Mythex
Когато приложението ви трябва да запазва данни, Mythex добавя към проекта отделна база Postgres – попитайте в чата или използвайте командата /database – и вкарва данните за връзка с нея в работното пространство и публикуваното приложение (Database). След това агентът пише кода, който чете и запазва вашите данни. Ако имате предпочитание – „използвай Prisma“, „използвай SQLAlchemy“ или „обикновен SQL, без ORM“ – кажете го в чата. Помолете го да ви обясни схемата, когато искате да проверите структурата; файловете можете да четете в редактора на кода. За по-голямата картина вижте какво е база данни и SQL срещу NoSQL.
Въпроси
Какво е ORM с прости думи?
ORM (object-relational mapper) е библиотека за код, която стои между приложението и релационната база данни. Тя позволява на разработчиците да четат и записват данни като обикновени обекти в техния език за програмиране, а SQL заявките ги пише зад кулисите.
Какви са примери за ORM?
Често използвани ORM са Prisma и Drizzle за TypeScript и JavaScript, SQLAlchemy и ORM-ът на Django за Python, Entity Framework Core за C#, Hibernate за Java и Active Record в Ruby on Rails.
По-добър ли е ORM от писане на SQL?
Зависи от задачата. ORM прави ежедневните четения и записи по-бързи за писане, по-безопасни и по-лесни за промяна, докато SQL, написан на ръка, дава пълен контрол при сложни отчети или заявки, критични за производителността. Повечето ORM позволяват да се спуснете до суров SQL, когато ви трябва.
Какво е миграция?
Миграцията е малък, версиран скрипт, който променя структурата на базата данни, например добавя таблица или колона. ORM може да генерира миграции от модела на данните, така че всяко копие на базата – на лаптоп, при тестване и в продукция – да получи една и съща структура.