Практика — лучший способ освоить новый инструмент и оценить все его преимущества. Обращаться к документации, писать в сообщество разработчиков — это здорово. Но не всегда достаточно. Если вы запутались в Object-Relational Mapping наша статья точно будет кстати.
Что такое Object-Relational Mapping
ORM (от английского — Object-Relational Mapping, дословный перевод, объектно-реляционное отображение) — это технология, которая обеспечивает взаимодействие между объектно-ориентированным кодом и реляционными БД и упрощает процесс программирования.
Благодаря преобразованию можно работать с данными в БД, используя объекты в своем программном коде, вместо того, чтобы напрямую писать SQL-запросы. Для этого Object-Relational Mapping автоматически преобразует объекты в записи таблиц базы данных и обратно. Это упрощает процесс разработки в объектно-ориентированных подходах, повышает уровень абстракции, позволяет работать с данными более интуитивным образом.
ORM формирует подобие такой «виртуальной объектной базы данных», которая существует лишь в коде приложения и затем синхронизируется уже с реальной базой данных.
Простыми словами, ORM — это инструмент для оптимизации работы с БД.
Зачем нужно Object-Relational Mapping
Технология нужна для того, чтобы упростить разработку и сопровождение кода. Представьте, что вам нужно получить список пользователей из базы данных и отсортировать их по имени. Без этой технологии вам пришлось бы написать сложный SQL-запрос и преобразовать результаты в объекты на языке программирования. С ней же этот процесс автоматизируется, и вы можете сделать это одной строкой кода:
users = session.query(User).order_by(User.name).all() |
Проблемы при работе с базами данных
Прямое взаимодействие с базами данных часто сопряжено с рядом негатива. Разработчику нужно писать сложные SQL-запросы, что требует глубокого знания синтаксиса SQL и также особенностей конкретной СУБД. Это может привести к ряду уже побочных сложностей:
- Написание сложных SQL-запросов — это трудоемкий процесс, особенно для неопытных разработчиков. Поддержка — тоже.
- При работе с разными таблицами часто приходится писать похожие запросы, что приводит к избыточности кода.
- Реляционная модель данных в БД не всегда соответствует объектной модели в коде приложения. Отсюда мы имеем дополнительные сложности при разработке.
Преимущества технологии
Рассмотрим наиболее важные из них.
Сокращение дублирования кода
Object-Relational Mapping позволяет значительно сократить объем повторяющегося кода при работе с базой данных глобально.
Пример: ручной SQL-запрос выглядит так:
INS ERT IN TO users (name, email, age) VALUES ('Ivan Petroff', '[email protected]', 30); |
А так это выглядит с использованием Object-Relational Mapping (на примере Python и SQLAlchemy):
user = User(name='Ivan Petrof', email='[email protected]', age=30) |
Повышение абстракции
Также Object-Relational Mapping предоставляет более высокий уровень абстракции, позволяя работать с объектами вместо прямого взаимодействия с таблицами и столбцами БД.
Абстракция данных позволяет разработчикам сфокусироваться на бизнес-логике приложения, а не на деталях работы с базой данных. Это упрощает разработку, улучшает читаемость кода, снижает вероятность ошибок. Да и вообще код становится более логичным, красивым.
Пример: вместо написания SQL-запроса…
SEL ECT name, email FR OM users WHERE id=1; |
…можно работать напрямую с объектами:
user = session.query(User).get(1) |
Улучшение переносимости
Технология обеспечивает независимость от конкретной СУБД, что упрощает перенос приложения между различными базами данных.
Object-Relational Mapping абстрагирует детали реализации конкретной СУБД, предоставляя унифицированный интерфейс для работы с разными базами данных. Это позволяет легко переключаться между различными СУБД без необходимости переписывать код приложения.
Пример: перенос приложения на другую СУБД без изменения кода Object-Relational Mapping будет достаточно наглядным для демонстрации этого преимущества. Предположим, вы используете SQLAlchemy с MySQL:
engine = create_engine('mysql://user:password@localhost/mydatabase') |
Для перехода на PostgreSQL достаточно изменить строку подключения:
engine = create_engine('postgresql://user:password@localhost/mydatabase') |
Код Object-Relational Mapping останется неизменным, что значительно упрощает процесс миграции.
Упрощение разработки
Инструмент существенно упрощает работу с базами данных и автоматизирует многие рутинные операции: создание таблиц, управление связями между объектами, генерацию SQL-запросов и многие другие аспекты работы с базами данных.
Больше не нужно сосредотачиваться на низкоуровневых деталях взаимодействия с каждой конкретной БД.
Пример: посмотрим как происходит создание, чтение, обновление и удаление данных с помощью Object-Relational Mapping:
# Создание |
Как использовать Object-Relational Mapping
Конечно, мы не сможем дать очень подробную инструкцию. Вместо этого приведем упрощенное руководство, но зато оно очень наглядно демонстрирует процесс работы с Object-Relational Mapping. Попробуем представить пошаговый пример использования ORM-фреймворка
Для примера возьмём связку Python и SQLAlchemy.
Шаг 1. Устанавливаем библиотеку:
```python |
Шаг 2. Создаем экземпляр класса `Engine`. Он будет использоваться для подключения к базе данных:
```python
|
Шаг 3. Создаем модель данных, которая будет соответствовать таблице в БД:
```python
|
Шаг 4. Создаем таблицу в базе данных, если она еще не существует:
```python Base.metadata.create_all(engine) |
Шаг 5. Используем простой `Session` для управления транзакциями и сессиями с базой данных:
```python |
Шаг 6. Записываем в базу данных:
```python |
Шаг 7. Получаем информацию из базы данных:
```python |
Примечание: код создает экземпляр класса Engine для подключения к базе данных SQLite. Далее добавляем модель данных User с колонками id, username и email. После создаем таблицу users в базе данных, добавляя нового пользователя с учетными данными Sergo и [email protected], сохраняем в базе данных и выводим имя пользователя (Sergo) из запроса к базе данных.
Говоря о том, как использовать технологию, нельзя не сказать о фреймворках.
Выбор ORM-фреймворка
Их очень много. Расскажу про пять самых популярных.
- Hibernate. Мощный ORM-фреймворк для Java, который поддерживает множество баз данных, предоставляет богатый функционал.
- Django ORM. Встроенный ORM в веб-фреймворк Django, оптимизирован для быстрой разработки веб-приложений на Python.
- SQLAlchemy. Гибкий, мощный ORM для питониста. Поддерживает и высокоуровневые абстракции, и низкоуровневое SQL-программирование.
- Entity Framework. ORM-фреймворк от Microsoft для .NET. Очень тесно интегрированн с экосистемой .NET.
- Sequelize. ORM-фреймворк для Node.js, есть удобный API для работы с данными. А еще поддержка множества разных баз данных уже из коробки.
Совет: рекомендую начинать с изучения наиболее распространенных фреймворков в вашей области разработки. Например, если вы работаете с Python, стоит начать с Django ORM или SQLAlchemy.
Самые ходовые фреймворки для пяти популярных языков:
- Java: Hibernate, JPA, Spring Data JPA, MyBatis.
- C#: Entity Framework, Dapper, NHibernate.
- PHP: Doctrine, Eloquent (Laravel), Propel.
- Ruby: ActiveRecord (Rails), Sequel, DataMapper.
- Jav * aScript: Sequelize, Knex, Objection.js.
Основные понятия Object-Relational Mapping
Отображение объектов на таблицы — ключевой маркет. Мы уже говорили в начале, но напомним основной принцип:
Object-Relational Mapping позволяет сопоставлять классы в коде с таблицами в базе данных. Каждый экземпляр класса представляет собой строку в соответствующей таблице.
Отображение атрибутов на столбцы
Атрибуты класса сопоставляются со столбцами таблицы. Технология автоматически преобразует типы данных между языком программирования и базой данных.
Операции CRUD (Create, Read, Update, Delete)
Object-Relational Mapping дает нам методы для выполнения основных операций с данными, так называемых CRUD-операций.
Связи между объектами
Object-Relational Mapping позволяет определять и управлять связями между объектами по разным сценариям: «один-ко-многим», «многие-ко-многим» и «один-к-одному».
Пример: описываем отображения класса «Пользователь» на таблицу «users»:
from sqlalchemy import Column, Integer, String |
Мы видим, что класс User отображается на таблицу users. Атрибуты класса (id, name, email, age) полностью соответствуют столбцам таблицы.
Более сложные концепции
В Object-Relational Mapping существует ряд и более сложных концепций, которые могут быть полезны при разработке сложных приложений.
Наследование. ORM позволяет отображать иерархии наследования классов на структуры таблиц в базе данных.
Полиморфизм. Некоторые такие технологии поддерживают полиморфные отношения, позволяя хранить объекты разных типов в одной таблице.
Ленивая загрузка. Техника оптимизации, при которой связанные объекты загружаются только при обращении к ним, что может улучшить производительность.
Кэширование. Многие подобные инструменты предоставляют механизмы кэширования для уменьшения количества запросов к базе данных и повышения производительности.
Для более глубокого изучения технологий нужно будет потратить время. Я рекомендую обратиться к официальной документации выбранного фреймворка или сразу же к специализированным ресурсам:
- Документация SQLAlchemy: https://docs.sqlalchemy.org/
- Руководство по Django ORM: https://docs.djangoproject.com/en/stable/topics/db/
- Hibernate ORM Documentation: https://hibernate.org/orm/documentation/
Коротко о главном
- Object-Relational Mapping — мощный инструмент, который значительно упрощает работу с базами данных в современных подходах программирования.
- Он позволяет работать с базами данных, используя обычные объекты сразу в коде вместо того, чтобы писать сложные запросы к базе данных, а также ускоряет процесс написания кода.
- Кроме того, сокращает объем кода и уменьшает дублирование, повышает уровень абстракции кода, улучшает переносимость приложений между различными СУБД и т. д.
Комментарии