TGStat
TGStat
Введите текст для поиска
Расширенный поиск каналов
  • flag Russian
    Язык сайта
    flag Russian flag English flag Uzbek
  • Вход на сайт
  • Каталог
    Каталог каналов и чатов Региональные подборки Тематические подборки Платные каналы Поиск каналов
    Добавить канал/чат
  • Рейтинги
    Рейтинг каналов Рейтинг чатов Рейтинг публикаций
    Рейтинги брендов и персон
  • Аналитика
  • Поиск по публикациям
  • Мониторинг Telegram
  • Продвижение
    Реклама через Яндекс Бизнес Реклама в каналах через TGStat Agency Реклама на сайте TGStat.ru
Советы разработчикам (python и не только)

11 Jan, 14:54

Открыть в Telegram Поделиться Пожаловаться

SQLAlchemy и ORM

SQLAlchemy в python предоставляет два набора API:

1. Возможность конструировать и выполнять запросы в БД
2. Получать и сохранять сущности

Первый набор api (Core функциональность) - это в первую очередь объекты запросов select, insert, update и других, а также метод execute, который есть у объекта Сonnection (можно использовать Session, но о нем ниже). Часто при этом используются объекты Table для описания структуры БД.

Кроме этого, sqlalchemy можно использовать как ORM. Это означает, что вы создаете классы, описывающие ваши сущности, а затем все операции с БД делаете только через них: вы загружаете сущности, сохраняете сущности, удаляете сущности (см. пост про стейт приложения и БД). При этом Connection вам уже недостаточно, вам требуется Session.

В чем ключевые отличия ORM подхода от Core?

• Для загрузки сущностей используется session.get для получения по первичному ключу или select(Model) запрос в других случаях. Обратите внимание, что речь идет именно о загрузке моделей целиком, а не отдельных полей таблиц. Кроме того, сессия реализует паттерн IdentityMap, то есть если объект уже загружен в память, то в некоторых случаях повторный запрос в БД не требуется (при get или загрузке связанных моделей), а если БД вернет одну сущность несколько раз, будет переиспользован один экземпляр.
• Для добавления новых сущностей мы используем метод session.add. Сессия реализует паттерн Unit of Work, поэтому все добавленные сущности будут хранится в промежуточном буфере и сохранятся при flush или commit. Если сущности содержат связи, они тоже будет автоматически добавлены. При чём алхимия следит за правильным порядком вставки и даже пытается оптимизировать запросы.
• Для применения изменений надо просто поменять сущности и закоммитить транзакцию. Опять же, благодаря Unit of work все изменения отслеживаются автоматически и не требуется вызывать никаких методов сохранения на каждом экземпляре вручную.
• Для удаления есть отдельный метод UoW - session.delete. Кроме непосредственно удаления сущности он так же следит за связями и обрабатывает их, зачастую более сложным способом чем умеет сама СУБД.

Таким образом, если вы используете модели алхимии, но вызываете insert или update, вы фактически не используете ORM. Так можно делать в целях оптимизации в отдельных нагруженных частях программы, но оно не должно восприниматься как основной способ работы с ORM.

Другой ошибкой является создание отдельных доменных сущностей одновременно с моделями ORM. Из-за этого приходится писать достаточно сложные мапперы, которые часто не учитывают наличие IdM и UoW, что может привести к некорректной логике сохранения данных. Вместо этого можно выделить три подхода:

• Не использовать ORM. Пишите сущности как вам удобно и сохраняйте в БД используя core-функциональность. Вы лишаетесь встроенного UoW, но и не конфликтуете с ним.
• Использовать модели ORM как бизнес сущности. Ваши сущности выглядят чуть более грязно, однако это только метаданные, которые в БЛ использоваться не будут.
• Использовать датаклассы и императивный маппинг, описывая отдельно Table объекты. Вы все ещё ограничены тем, что алхимия меняет модели, внедряя скрытые атрибуты, но ваша БЛ уже это не видит. Вы не можете использовать совсем кастомные мапперы для отдельных моделей, но зато имеете все возможности алхимии.

Даже используя ORM приходится писать сложные select запросы для реализации поиска или получения сводной информации, поэтому имеет смысл реализовать паттерн репозиторий, скрывая их построение внутри, но при этом мы все ещё полагаемся на возможности сессии как UoW.

Кроме того, в нашем приложении кроме логики работы с сущностями могут существовать запросы чтения, возвращающие клиенту определенный срез данных. Для этого мы можем реализовать простой DAO, использующий Core алхимии или описать альтернативные модели, которые будут императивно маппиться на те же таблицы, но иметь другую структуру.

Дополнительные материалы:
• Mapping SQLAlchemy to dataclass
• Mapping a Class against Multiple Tables
• Patterns Implemented by SQLAlchemy

5.5k 8 114 56 158
Каталог
Каталог каналов и чатов Подборки каналов Поиск каналов Добавить канал/чат
Рейтинги
Рейтинг каналов Telegram Рейтинг чатов Telegram Рейтинг публикаций Рейтинги брендов и персон
API
API статистики API поиска публикаций API Callback
Наши каналы
@TGStat @TGStat_Chat @telepulse @TGStatAPI
Почитать
Академия TGStat Исследование Telegram 2019 Исследование Telegram 2021 Исследование Telegram 2023
Контакты
Справочный центр Поддержка Почта Вакансии
Всякая всячина
Пользовательское соглашение Политика конфиденциальности Публичная оферта
Наши боты
@TGStat_Bot @SearcheeBot @TGAlertsBot @tg_analytics_bot @TGStatChatBot