ORM
ORM — це скорочення від Object-Relational Mapping, тобто об’єктно-реляційне відображення. ORM дозволяє програмі працювати з даними бази не напряму через SQL-запити, а через об’єкти, класи, моделі та сутності в коді.
Простіше кажучи, ORM перетворює таблиці бази даних на об’єкти програми. Наприклад, таблиця Customers може відповідати класу Customer, таблиця Orders — класу Order, а рядок у таблиці — конкретному об’єкту в коді.
ORM часто використовується в ERP, CRM, e-commerce, фінансових системах, складських системах, HRM, Service Desk, BI-платформах, API та веб-додатках. У контексті K2 ERP ORM може бути частиною серверної логіки, яка працює з довідниками, документами, користувачами, ролями, замовленнями, платежами, залишками, договорами, номенклатурою та аналітичними даними.
Головне. ORM допомагає програмісту працювати з базою даних як з об’єктами: створити клієнта, знайти замовлення, змінити статус рахунку, зберегти платіж або отримати список товарів без ручного написання кожного SQL-запиту.
Практичний приклад. Замість SQL-запиту SELECT * FROM orders WHERE customer_id = 15 ORM дозволяє написати щось схоже на customer.orders або Order.findByCustomer(customer). Код стає ближчим до бізнес-логіки.
Важливо. ORM не скасовує SQL і не робить базу даних “простою автоматично”. Якщо неправильно будувати моделі, зв’язки й запити, ORM може створювати повільні запити, дублювати дані, перевантажувати сервер і приховувати помилки архітектури.
Що таке ORM
ORM — це технологія, яка зв’язує об’єктну модель програми з реляційною базою даних.
У програмі розробник працює з об’єктами:
- клієнт;
- замовлення;
- рахунок;
- товар;
- платіж;
- користувач;
- роль;
- склад;
- договір;
- документ.
У базі даних ці самі дані зберігаються в таблицях:
- customers;
- orders;
- invoices;
- products;
- payments;
- users;
- roles;
- warehouses;
- contracts;
- documents.
ORM відповідає за перетворення між цими двома світами.
Простий приклад ORM
Є таблиця клієнтів у базі даних.
| id | name | phone | |
|---|---|---|---|
| 1 | ТОВ “Клієнт Плюс” | info@example.com | +380XXXXXXXXX |
| 2 | ФОП Іваненко | ivanenko@example.com | +380XXXXXXXXX |
У коді ця таблиця може виглядати як клас:
class Customer:
id
name
email
phone
А конкретний рядок таблиці стає об’єктом:
customer.name = "ТОВ Клієнт Плюс" customer.email = "info@example.com"
ORM допомагає отримати цей об’єкт із бази, змінити його й зберегти назад.
Для чого потрібен ORM
ORM потрібен, щоб спростити роботу програми з базою даних.
Він допомагає:
- створювати записи;
- читати записи;
- оновлювати записи;
- видаляти записи;
- описувати зв’язки між таблицями;
- працювати з транзакціями;
- зменшувати кількість ручного SQL;
- робити код зрозумілішим;
- повторно використовувати моделі;
- будувати API;
- підтримувати бізнес-логіку;
- контролювати цілісність даних;
- пришвидшувати розробку ERP або CRM.
Як працює ORM
ORM працює як посередник між кодом і базою даних.
Типовий ланцюг виглядає так:
- Програміст описує модель.
- ORM знає, якій таблиці відповідає модель.
- Код створює або змінює об’єкт.
- ORM формує SQL-запит.
- База даних виконує запит.
- ORM повертає результат у вигляді об’єкта.
Приклад без ORM
Без ORM програміст може писати SQL вручну:
SELECT id, name, email FROM customers WHERE id = 15;
Потім потрібно вручну перетворити результат у структуру програми.
Якщо треба змінити email клієнта:
UPDATE customers SET email = 'new@example.com' WHERE id = 15;
Це працює, але в великій ERP-системі таких запитів можуть бути тисячі.
Приклад з ORM
З ORM код може виглядати простіше:
customer = Customer.get(id=15) customer.email = "new@example.com" customer.save()
ORM сам сформує SQL-запит до бази.
Для програміста це виглядає як робота з об’єктом, а не з таблицею.
ORM і CRUD
CRUD — це базові операції з даними:
| Операція | Що означає | Приклад в ERP |
|---|---|---|
| Create | Створити запис | Створити нового клієнта |
| Read | Прочитати запис | Відкрити замовлення |
| Update | Оновити запис | Змінити статус рахунку |
| Delete | Видалити запис | Видалити чернетку документа |
ORM зазвичай надає зручні методи для всіх цих операцій.
Приклад CRUD для клієнта
| Дія | Приклад | Що робить ORM |
|---|---|---|
| Створити | Customer.create(name="ТОВ Альфа")
|
Додає рядок у таблицю customers |
| Прочитати | Customer.get(id=10)
|
Виконує SELECT |
| Оновити | customer.phone = "+380..."
|
Готує UPDATE |
| Видалити | customer.delete()
|
Виконує DELETE або м’яке видалення |
ORM і моделі
Модель — це клас або структура, яка описує дані певного бізнес-об’єкта.
Приклади моделей в ERP:
- Customer — клієнт;
- Supplier — постачальник;
- Product — товар;
- Order — замовлення;
- Invoice — рахунок;
- Payment — платіж;
- Contract — договір;
- Warehouse — склад;
- Employee — працівник;
- User — користувач.
Приклад моделі товару
class Product:
id
sku
name
unit
price
active
У базі це може бути таблиця:
| Поле | Тип | Приклад |
|---|---|---|
| id | integer | 101 |
| sku | text | USB-C-1M-BLK |
| name | text | Кабель USB-C 1 м чорний |
| unit | text | шт. |
| price | decimal | 180.00 |
| active | boolean | true |
ORM і сутності
Сутність — це бізнес-об’єкт, який має значення для системи.
У CRM сутністю може бути клієнт. У складі — товар. У фінансах — платіж. У документообігу — договір. У HRM — працівник. У ERP — документ, замовлення, рахунок, підрозділ або організація.
ORM дозволяє описати ці сутності як об’єкти коду.
ORM і таблиці бази даних
ORM пов’язує клас із таблицею.
| Об’єкт у коді | Таблиця в базі | Приклад |
|---|---|---|
| Customer | customers | Клієнти |
| Product | products | Номенклатура |
| Order | orders | Замовлення |
| Payment | payments | Платежі |
| Contract | contracts | Договори |
| User | users | Користувачі |
ORM і поля
Поля моделі відповідають колонкам таблиці.
Наприклад, модель Order може мати поля:
- id;
- number;
- date;
- customer_id;
- status;
- total_amount;
- currency;
- created_at;
- updated_at.
У базі це будуть колонки таблиці orders.
ORM і зв’язки між таблицями
У реальних системах таблиці пов’язані між собою.
Типові зв’язки:
- один до одного;
- один до багатьох;
- багато до багатьох.
ORM дозволяє описати ці зв’язки на рівні моделей.
Зв’язок один до багатьох
Один клієнт може мати багато замовлень.
| Сутність | Зв’язок | Приклад |
|---|---|---|
| Customer | має багато Order | Клієнт має 25 замовлень |
| Order | належить Customer | Замовлення належить конкретному клієнту |
У коді це може виглядати так:
customer = Customer.get(id=15) orders = customer.orders
ORM сам знайде замовлення цього клієнта.
Зв’язок багато до багатьох
Один користувач може мати багато ролей, а одна роль може бути в багатьох користувачів.
| Сутність | Зв’язок | Приклад |
|---|---|---|
| User | має багато Role | Користувач є менеджером і погоджувачем |
| Role | має багато User | Роль “Менеджер” має 15 користувачів |
Для цього в базі часто створюється проміжна таблиця:
- users;
- roles;
- user_roles.
Приклад ORM для ERP-замовлення
Замовлення клієнта може містити шапку й рядки.
Шапка замовлення:
| Поле | Приклад |
|---|---|
| number | ORD-000145 |
| customer | ТОВ “Клієнт Плюс” |
| date | 15.05.2026 |
| status | Нове |
| total | 24 500 грн |
Рядки замовлення:
| Товар | Кількість | Ціна | Сума |
|---|---|---|---|
| Кабель USB-C | 100 шт. | 180 грн | 18 000 грн |
| Зарядний адаптер | 50 шт. | 130 грн | 6 500 грн |
У ORM це можуть бути дві моделі:
- Order;
- OrderLine.
Приклад моделей Order і OrderLine
class Order:
id
number
customer
date
status
total_amount
lines
class OrderLine:
id
order
product
quantity
price
amount
Зв’язок:
- одне замовлення має багато рядків;
- кожен рядок належить одному замовленню;
- кожен рядок посилається на товар.
ORM і SQL
ORM не замінює SQL повністю. Він генерує SQL або виконує запити до бази через власний механізм.
Наприклад, код:
orders = Order.filter(status="paid")
може перетворитися на SQL:
SELECT * FROM orders WHERE status = 'paid';
Розробник може не писати SQL напряму, але має розуміти, які запити реально виконує ORM.
ORM і транзакції
Транзакція — це група операцій, які мають виконатися разом або не виконатися взагалі.
Приклад в ERP:
- Створити платіж.
- Зменшити залишок коштів.
- Закрити борг постачальника.
- Записати рух у регістр.
- Додати запис в аудит.
Якщо одна дія не виконалась, потрібно відкотити всі інші.
ORM часто підтримує транзакції, щоб зберігати цілісність даних.
Приклад транзакції
Компанія проводить оплату постачальнику на 80 000 грн.
У межах однієї транзакції система має:
- створити платіжний документ;
- записати рух коштів;
- зменшити залишок банківського рахунку;
- закрити кредиторську заборгованість;
- оновити статус заявки;
- записати аудит дії.
Якщо помилка сталася на етапі закриття боргу, платіж не повинен залишитися “наполовину проведеним”.
ORM і міграції бази даних
Міграції бази даних — це контрольовані зміни структури таблиць.
Наприклад, потрібно додати в замовлення поле delivery_status.
Міграція може виконати:
ALTER TABLE orders ADD COLUMN delivery_status VARCHAR(50);
ORM-фреймворки часто мають власний механізм міграцій, щоб структура бази відповідала моделям у коді.
Приклад міграції
Компанія хоче додати в модель клієнта поле “канал залучення”.
Було:
| Customer | Поля |
|---|---|
| Клієнт | id, name, phone, email |
Стало:
| Customer | Поля |
|---|---|
| Клієнт | id, name, phone, email, source_channel |
Після міграції можна аналізувати, звідки прийшов клієнт:
- сайт;
- рекомендація;
- маркетплейс;
- виставка;
- холодний дзвінок;
- партнер.
ORM і ліниве завантаження
Ліниве завантаження означає, що пов’язані дані завантажуються тільки тоді, коли вони реально потрібні.
Наприклад:
customer = Customer.get(id=15) orders = customer.orders
Спочатку ORM отримує клієнта. Замовлення завантажуються тільки тоді, коли код звернувся до customer.orders.
Це зручно, але може створити проблему продуктивності.
Проблема N+1 запитів
N+1 — одна з найвідоміших проблем ORM.
Приклад:
- система отримала 100 клієнтів;
- потім для кожного клієнта окремо отримала його замовлення;
- замість 1–2 запитів до бази виконалось 101 запит.
Це може сильно уповільнити ERP, CRM або інтернет-магазин.
Приклад N+1 у продажах
Потрібно показати список клієнтів і суму їхніх замовлень.
Поганий сценарій:
- Отримати 500 клієнтів.
- Для кожного клієнта окремо запитати замовлення.
- Отримати 501 запит до бази.
Кращий сценарій:
- завантажити клієнтів разом із агрегованими продажами;
- використати JOIN;
- використати eager loading;
- використати окремий оптимізований SQL-запит;
- побудувати аналітичну таблицю.
ORM і eager loading
Eager loading — це попереднє завантаження пов’язаних даних.
Наприклад, одразу отримати замовлення разом із клієнтами й рядками:
orders = Order.with(customer, lines).filter(status="paid")
Це може зменшити кількість запитів і прискорити сторінку.
ORM і кешування
ORM може працювати з кешем, щоб не запитувати одні й ті самі дані багато разів.
Кешування корисне для:
- довідників;
- валют;
- одиниць виміру;
- ролей;
- налаштувань;
- типів документів;
- статусів;
- прав доступу;
- прайсів, якщо вони не змінюються щосекунди.
Але кеш потрібно правильно оновлювати, інакше користувачі бачитимуть старі дані.
ORM і продуктивність
ORM спрощує код, але може створювати приховані проблеми продуктивності.
Типові ризики:
- занадто багато SQL-запитів;
- N+1 проблема;
- зайве завантаження великих об’єктів;
- неправильні індекси;
- повільні JOIN;
- відсутність пагінації;
- завантаження всіх рядків одразу;
- складні фільтри без оптимізації;
- надмірні транзакції;
- повільні міграції.
Приклад проблеми продуктивності
Сторінка “Продажі за рік” відкриває всі документи реалізації, всі рядки, всіх клієнтів, всю номенклатуру й усі платежі.
Якщо це робити через ORM без оптимізації:
- база виконує тисячі запитів;
- сторінка відкривається 30 секунд;
- сервер перевантажується;
- користувачі думають, що ERP “гальмує”;
- проблема насправді в неправильному використанні ORM.
ORM і індекси
ORM не скасовує потребу в індексах бази даних.
Індекси потрібні для швидкого пошуку за:
- id;
- номером документа;
- датою;
- клієнтом;
- договором;
- статусом;
- артикулом;
- складом;
- організацією;
- зовнішнім ID;
- email;
- телефоном.
Приклад індексу
Якщо ERP часто шукає замовлення за зовнішнім ID сайту:
external_order_id = "WEB-10425"
то поле external_order_id має бути індексованим.
Інакше база може переглядати тисячі або мільйони рядків.
ORM і валідація даних
ORM часто дозволяє описувати правила перевірки даних.
Приклади:
- email має бути коректним;
- сума платежу не може бути від’ємною;
- замовлення має мати клієнта;
- товар має мати артикул;
- дата документа не може бути порожньою;
- статус має бути зі списку дозволених;
- кількість у рядку має бути більшою за нуль.
Приклад валідації
Для платіжного документа можна задати правила:
| Поле | Правило |
|---|---|
| amount | Сума більше 0 |
| currency | Валюта обов’язкова |
| counterparty | Контрагент обов’язковий |
| contract | Договір обов’язковий |
| payment_date | Дата обов’язкова |
Такі перевірки допомагають не зберігати “биті” документи.
ORM і бізнес-логіка
Частина бізнес-логіки може бути в моделях ORM.
Наприклад, модель Order може мати методи:
- calculate_total;
- apply_discount;
- reserve_stock;
- change_status;
- cancel_order;
- create_invoice;
- check_credit_limit.
Але важливо не перевантажувати ORM-моделі всією логікою. У великих ERP краще розділяти:
- моделі даних;
- сервіси;
- бізнес-процеси;
- API;
- аналітику;
- права доступу.
ORM в ERP
В ERP ORM може використовуватися для роботи з основними бізнес-об’єктами.
Приклади:
- організації;
- підрозділи;
- користувачі;
- ролі;
- контрагенти;
- договори;
- номенклатура;
- склади;
- замовлення;
- закупівлі;
- продажі;
- платежі;
- залишки;
- бюджети;
- виробництво;
- сервісні заявки.
Приклад ORM в ERP
Менеджер створює замовлення клієнта.
ORM може виконати такі дії:
- Створити об’єкт Order.
- Додати клієнта.
- Додати рядки товарів.
- Перевірити ціни.
- Перевірити залишки.
- Зберегти замовлення.
- Створити резерв.
- Записати аудит.
- Повернути номер документа.
ORM в CRM
У CRM ORM може працювати з такими сутностями:
- lead;
- contact;
- company;
- deal;
- task;
- call;
- email;
- note;
- pipeline;
- stage;
- user.
Приклад:
deal = Deal.create(
customer=customer,
amount=50000,
stage="proposal"
)
ORM зберігає угоду й пов’язує її з клієнтом.
ORM у складській системі
У складі ORM може описувати:
- товар;
- склад;
- комірку;
- партію;
- серійний номер;
- залишок;
- переміщення;
- інвентаризацію;
- списання;
- резерв.
Приклад:
stock = StockBalance.get(product=product, warehouse=warehouse) stock.quantity = stock.quantity - 10 stock.save()
Для реальної ERP це має виконуватися в транзакції з перевіркою залишків.
ORM у фінансах
У фінансах ORM може працювати з:
- платежами;
- банківськими рахунками;
- касами;
- валютами;
- курсами;
- договорами;
- дебіторкою;
- кредиторкою;
- бюджетами;
- статтями витрат;
- заявками на оплату.
Приклад:
payment = Payment.create(
counterparty=supplier,
amount=80000,
currency="UAH",
contract=contract
)
ORM і права доступу
ORM сам по собі не завжди вирішує права доступу, але може бути частиною механізму безпеки.
Наприклад:
- користувач бачить тільки свої замовлення;
- бухгалтер бачить документи своєї організації;
- комірник бачить тільки свій склад;
- менеджер не бачить собівартість;
- HR бачить тільки кадрові дані;
- API-користувач може тільки читати залишки.
Приклад обмеження доступу
Користувач має доступ тільки до складу №1.
Запит:
StockBalance.filter(warehouse=user.allowed_warehouse)
У результаті користувач не побачить залишки інших складів.
У великій ERP такі обмеження мають бути централізованими, а не розкиданими по коду.
ORM і API
ORM часто використовується за API.
Наприклад, API отримує запит:
GET /api/orders/10425
Сервер через ORM шукає замовлення:
order = Order.get(number="10425")
Потім повертає відповідь у JSON.
Приклад API + ORM
Сайт створює замовлення через API.
| Крок | Що відбувається |
|---|---|
| 1 | API отримує JSON із сайту |
| 2 | ORM шукає клієнта по телефону |
| 3 | ORM шукає товари по артикулу |
| 4 | ORM створює замовлення |
| 5 | ORM створює рядки замовлення |
| 6 | Система повертає номер замовлення |
ORM і інтеграції
У системах інтеграції ORM може використовуватися для збереження зовнішніх даних.
Приклади:
- замовлення з сайту;
- клієнти з CRM;
- платежі з банку;
- залишки з WMS;
- виробничі операції з MES;
- статуси доставки;
- документи ЕДО;
- дані для Power BI.
ORM і зовнішній ID
Для інтеграцій важливо зберігати зовнішні ідентифікатори.
Наприклад:
| Система | Зовнішній ID | Поле в ORM-моделі |
|---|---|---|
| Сайт | WEB-10425 | external_order_id |
| CRM | CRM-CUST-777 | external_customer_id |
| Банк | BANK-PAY-991 | external_payment_id |
| WMS | WMS-SHIP-2026 | external_shipment_id |
Це допомагає не створювати дублікати.
ORM і аудит дій
У бізнес-системах важливо знати, хто змінив дані.
ORM може автоматично заповнювати поля:
- created_at;
- updated_at;
- created_by;
- updated_by;
- deleted_at;
- deleted_by.
Також можна вести окремий журнал змін.
Приклад аудиту
Користувач змінив банківський рахунок постачальника.
Система має записати:
| Поле | Значення |
|---|---|
| object_type | SupplierBankAccount |
| object_id | 145 |
| action | update |
| user | buh01 |
| old_value | UA старий рахунок |
| new_value | UA новий рахунок |
| time | 15.05.2026 10:45 |
ORM і soft delete
Soft delete — це м’яке видалення.
Замість фізичного видалення рядка з бази ORM ставить ознаку:
- deleted = true;
- deleted_at;
- deleted_by.
Це корисно для ERP, бо документи, договори, платежі й довідники часто не можна просто видаляти без сліду.
Приклад soft delete
Користувач видаляє товар, який уже був у продажах.
Фізичне видалення небезпечне, бо старі документи втратять посилання.
Краще:
- позначити товар неактивним;
- заборонити нові операції;
- залишити історію продажів;
- зберегти зв’язки в документах.
ORM і багатокомпанійність
ERP часто працює з кількома організаціями або компаніями.
ORM-моделі можуть містити поле:
- organization_id;
- company_id;
- tenant_id.
Це дозволяє розділяти дані між організаціями.
Приклад багатокомпанійності
Один користувач бачить тільки документи ТОВ “Компанія”.
Запит має враховувати організацію:
orders = Order.filter(organization=user.organization)
Якщо це правило забути, користувач може побачити документи іншої юридичної особи.
ORM і multi-tenant системи
Multi-tenant — це архітектура, коли одна система обслуговує багато клієнтів або компаній.
У такому випадку ORM має дуже уважно фільтрувати дані за tenant_id.
Ризик:
- клієнт А може побачити дані клієнта Б;
- API поверне чужі документи;
- Power BI отримає неправильний зріз;
- аудит стане некоректним.
ORM і звітність
ORM зручний для операційної роботи, але не завжди ідеальний для складної аналітики.
Для звітів часто краще використовувати:
- оптимізовані SQL-запити;
- матеріалізовані представлення;
- аналітичні таблиці;
- OLAP;
- BI-сховище;
- Power BI;
- окремі агрегати;
- ETL-процеси.
Приклад: звіт по маржі
Звіт по маржі може потребувати:
- продажі;
- собівартість;
- знижки;
- повернення;
- валютні курси;
- договори;
- менеджерів;
- підрозділи;
- товарні групи.
Якщо робити такий звіт тільки через ORM і завантажувати всі об’єкти, він може бути повільним. Краще підготувати аналітичний запит або BI-модель.
ORM і Power BI
Power BI зазвичай не працює напряму з ORM-моделями. Він бере дані з бази, API, файлів або сховища.
Але ORM впливає на якість даних:
- як названі таблиці;
- чи є зовнішні ID;
- чи є статуси;
- чи є аудит;
- чи немає дублів;
- чи правильно зберігаються зв’язки;
- чи є created_at і updated_at;
- чи можна будувати інкрементальне оновлення.
ORM і K2 ERP
У K2 ERP або подібній ERP-платформі ORM може використовуватися як технічний шар роботи з даними.
ORM може допомагати працювати з:
- довідниками;
- документами;
- користувачами;
- ролями;
- договорами;
- платежами;
- складськими залишками;
- замовленнями;
- виробничими операціями;
- сервісними заявками;
- API;
- аудитом;
- інтеграціями;
- Power BI-вивантаженнями.
Переваги ORM
Основні переваги ORM:
- швидша розробка;
- менше ручного SQL;
- зрозуміліші моделі;
- повторне використання коду;
- зручна робота зі зв’язками;
- підтримка транзакцій;
- міграції структури бази;
- валідація даних;
- інтеграція з API;
- краща читабельність бізнес-логіки.
Недоліки ORM
Недоліки ORM:
- приховані SQL-запити;
- ризик повільної роботи;
- N+1 проблема;
- складність оптимізації;
- надмірне завантаження даних;
- не завжди підходить для складної аналітики;
- залежність від фреймворку;
- ризик неправильної моделі;
- складність при великих обсягах даних;
- ілюзія, що SQL знати не потрібно.
ORM не замінює SQL
Навіть якщо система використовує ORM, розробнику важливо розуміти SQL.
Потрібно знати:
- SELECT;
- JOIN;
- WHERE;
- GROUP BY;
- ORDER BY;
- індекси;
- транзакції;
- блокування;
- плани виконання;
- нормалізацію;
- обмеження цілісності;
- оптимізацію запитів.
Коли ORM підходить
ORM добре підходить для:
- CRUD-додатків;
- ERP-довідників;
- CRM-сутностей;
- адміністративних панелей;
- API;
- бізнес-документів;
- невеликих і середніх транзакцій;
- роботи з користувачами;
- роботи з ролями;
- операційних процесів.
Коли ORM може бути поганим вибором
ORM може бути не найкращим варіантом для:
- дуже складної аналітики;
- великих batch-операцій;
- масового імпорту мільйонів рядків;
- складних фінансових розрахунків;
- високонавантажених звітів;
- складних SQL-оптимізацій;
- ETL-процесів;
- систем реального часу з дуже високими вимогами до продуктивності.
У таких випадках можна комбінувати ORM із ручним SQL.
Популярні ORM-підходи
У різних мовах програмування існують свої ORM або ORM-подібні інструменти.
Приклади:
- Active Record;
- Data Mapper;
- Repository;
- Unit of Work;
- Entity Manager;
- Query Builder.
Active Record
Active Record — це підхід, у якому модель сама вміє зберігати себе в базі.
Приклад:
customer = Customer(name="ТОВ Альфа") customer.save()
Модель Customer одночасно є і бізнес-об’єктом, і об’єктом доступу до бази.
Data Mapper
Data Mapper відокремлює об’єкти бізнес-логіки від механізму збереження.
У цьому підході окремий шар відповідає за те, як об’єкти записуються в базу.
Це може бути складніше, але краще підходить для великих систем зі складною логікою.
Repository
Repository — це шаблон, який приховує деталі доступу до даних.
Наприклад:
customerRepository.findById(15)
orderRepository.findPaidOrders()
productRepository.findBySku("USB-C-1M-BLK")
Код бізнес-логіки не знає, чи дані прийшли з ORM, SQL, API або кешу.
Unit of Work
Unit of Work відстежує зміни об’єктів і зберігає їх разом.
Наприклад:
- створили замовлення;
- додали рядки;
- змінили залишки;
- створили резерв;
- записали аудит.
Unit of Work може зберегти все в межах однієї транзакції.
ORM і тестування
ORM-моделі потрібно тестувати.
Перевіряють:
- створення записів;
- оновлення;
- видалення;
- зв’язки;
- транзакції;
- валідацію;
- обмеження доступу;
- поведінку при помилках;
- міграції;
- продуктивність запитів.
Приклад тесту бізнес-логіки
Для замовлення можна перевірити:
- замовлення не створюється без клієнта;
- рядок не може мати кількість 0;
- сума замовлення рахується правильно;
- статус не можна змінити з “скасовано” на “відвантажено”;
- замовлення не проводиться без товарів;
- резерв створюється тільки за наявності залишку.
ORM і безпека
ORM може зменшити ризик SQL-ін’єкцій, якщо правильно використовувати параметризовані запити.
Але безпека залежить не тільки від ORM.
Потрібно контролювати:
- права доступу;
- фільтрацію за організацією;
- фільтрацію за користувачем;
- API-доступи;
- масове оновлення;
- експорт даних;
- аудит змін;
- доступ до персональних даних;
- доступ до зарплати;
- доступ до банківських реквізитів.
ORM і помилки архітектури
Типові помилки:
- модель повторює таблицю без бізнес-сенсу;
- у модель додали занадто багато логіки;
- усі зв’язки зроблені eager loading;
- усі зв’язки зроблені lazy loading;
- немає індексів;
- немає транзакцій;
- немає soft delete;
- немає аудиту;
- немає обмежень доступу;
- великі звіти будуються через ORM без оптимізації;
- бізнес-логіка розкидана по контролерах, моделях і SQL.
Приклад поганої ORM-моделі
Модель Order містить:
- дані замовлення;
- логіку знижок;
- логіку складу;
- логіку платежів;
- логіку доставки;
- логіку email;
- логіку PDF;
- логіку інтеграції з сайтом;
- логіку аналітики.
Така модель стає занадто великою й складною. Краще винести частину логіки в сервіси.
Приклад хорошої ORM-архітектури
У кращому варіанті:
- модель Order описує дані замовлення;
- OrderService керує бізнес-логікою;
- StockService відповідає за залишки;
- PaymentService відповідає за оплати;
- NotificationService надсилає повідомлення;
- AuditService записує історію змін;
- Repository відповідає за пошук і збереження.
ORM у міграції даних
ORM може використовуватися для перенесення даних, але з обережністю.
Для невеликих обсягів ORM зручний:
- прочитати клієнтів;
- створити товари;
- перенести довідники;
- створити користувачів;
- перенести налаштування.
Для великих обсягів краще використовувати:
- bulk insert;
- ETL;
- прямі SQL-запити;
- черги;
- пакетну обробку;
- контрольні суми.
Приклад міграції через ORM
Потрібно перенести список контрагентів у нову ERP.
ORM може виконати:
- Прочитати контрагента з джерела.
- Перевірити ЄДРПОУ.
- Знайти дублікати.
- Створити Customer або Supplier.
- Додати договори.
- Зберегти зовнішній ID.
- Записати результат міграції.
ORM і контрольні суми
При міграції через ORM важливо рахувати контрольні суми.
Наприклад:
| Об’єкт | У старій системі | У новій системі | Статус |
|---|---|---|---|
| Клієнти | 12 450 | 12 450 | Збігається |
| Товари | 8 200 | 8 198 | Потрібна перевірка |
| Замовлення | 240 000 | 240 000 | Збігається |
| Платежі | 95 000 | 94 990 | Потрібна перевірка |
ORM і логування
Для підтримки ORM важливо логувати:
- SQL-запити;
- повільні запити;
- помилки транзакцій;
- помилки валідації;
- помилки міграцій;
- кількість запитів на сторінку;
- час виконання;
- користувача;
- API-запит;
- змінені об’єкти.
Типові помилки при використанні ORM
Поширені помилки:
- не дивитися на SQL, який генерує ORM;
- завантажувати всі записи без фільтра;
- не використовувати пагінацію;
- ігнорувати N+1;
- не створювати індекси;
- не використовувати транзакції;
- видаляти дані фізично без аудиту;
- зберігати бізнес-логіку хаотично;
- не тестувати міграції;
- використовувати ORM для всіх звітів без винятку;
- не контролювати права доступу.
Переваги правильного використання ORM
Правильно використаний ORM дає:
- зрозумілий код;
- швидшу розробку;
- менше дублювання SQL;
- стабільні моделі;
- кращу підтримку API;
- зручні міграції;
- контроль транзакцій;
- кращу тестованість;
- простіше масштабування команди;
- чистішу бізнес-логіку.
Що потрібно знати перед вибором ORM
Перед вибором ORM варто оцінити:
- мову програмування;
- базу даних;
- складність доменної моделі;
- обсяг даних;
- вимоги до продуктивності;
- складність звітів;
- потребу в транзакціях;
- потребу в міграціях;
- досвід команди;
- підтримку індексів;
- підтримку raw SQL;
- інтеграцію з API;
- підтримку тестування.
ORM у великих ERP-проєктах
У великих ERP-проєктах ORM зазвичай не є єдиним способом роботи з даними.
Можуть одночасно використовуватися:
- ORM для бізнес-операцій;
- SQL для складної звітності;
- ETL для міграцій;
- кеш для довідників;
- черги для інтеграцій;
- API для зовнішніх систем;
- Power BI для аналітики;
- audit log для змін;
- окремі сервіси для складної логіки.
Пов’язані сторінки
- ERP
- K2 ERP
- API для ERP
- BI система
- Power BI
- CRM для продажів
- ERP для складу
- ERP для виробництва
- Казначейство
- Service Desk
- Права доступу в ERP
- Аудит дій
- Міграція даних
- Вивантаження даних
- Інтеграція з BAS
- ERP в хмарі
- Впровадження ERP
- Запуск ERP
FAQ
Що таке ORM простими словами?
ORM — це технологія, яка дозволяє працювати з таблицями бази даних як з об’єктами в коді. Наприклад, клієнт, товар або замовлення стають моделями програми.
Для чого потрібен ORM?
ORM потрібен, щоб швидше й зручніше створювати, читати, оновлювати й видаляти дані без ручного написання кожного SQL-запиту.
Чи замінює ORM SQL?
Ні. ORM генерує SQL або виконує запити до бази, але розробнику все одно потрібно розуміти SQL, індекси, транзакції, JOIN і продуктивність.
Що таке модель в ORM?
Модель — це клас або структура в коді, яка відповідає таблиці бази даних. Наприклад, модель Product може відповідати таблиці products.
Що таке зв’язки в ORM?
Зв’язки описують відношення між моделями: один клієнт має багато замовлень, одне замовлення має багато рядків, користувач може мати багато ролей.
Що таке N+1 проблема в ORM?
N+1 — це ситуація, коли ORM виконує один запит для списку об’єктів і потім ще окремий запит для кожного об’єкта. Це може сильно уповільнити систему.
Чи підходить ORM для ERP?
Так, ORM добре підходить для багатьох ERP-операцій: довідників, документів, користувачів, ролей, замовлень, платежів, договорів і API. Але для складної аналітики часто потрібні оптимізовані SQL-запити або BI-шар.
Які ризики ORM?
Основні ризики — повільні запити, N+1 проблема, зайве завантаження даних, відсутність індексів, неправильні транзакції, слабка модель доступу й надмірна залежність від фреймворку.
Чи можна використовувати ORM для міграції даних?
Так, але для великих обсягів даних ORM може бути повільним. Часто краще комбінувати ORM, bulk insert, ETL, SQL-запити й контрольні суми.
Який результат правильного використання ORM?
Результат — зрозумілий код, швидша розробка, чистіші моделі, контроль транзакцій, зручні API, менше ручного SQL і краща підтримка бізнес-логіки.
Коротко
| Питання | Відповідь |
|---|---|
| Що таке ORM? | Object-Relational Mapping — перетворення таблиць бази даних на об’єкти в коді. |
| Для чого потрібен? | Для зручної роботи з даними: створення, читання, оновлення, видалення, зв’язків і транзакцій. |
| Що є основою ORM? | Моделі, сутності, таблиці, поля, зв’язки, запити, транзакції й міграції. |
| Чи замінює ORM SQL? | Ні, SQL усе одно потрібно розуміти для оптимізації, звітів, індексів і складних запитів. |
| Де використовується? | В ERP, CRM, сайтах, API, фінансових системах, складах, HRM, Service Desk і BI-рішеннях. |
| Які головні ризики? | N+1 запити, повільна робота, зайве завантаження даних, неправильні індекси й слабкий контроль доступу. |
| Який результат? | Чистіший код, швидша розробка, зручні моделі, контроль даних і простіша підтримка бізнес-систем. |