orm sequelize что это

ORM-система Sequelize для Node.js

В этом уроке мы узнаем, что такое ORM, зачем он нужен, какие ORM библиотеки есть для Node.js и как с ними работать.

ORM (англ. Object-Relational Mapping, рус. объектно-реляционное отображение) — это технология программирования, который связывает базу данных с моделью объектно-ориентированных языков программирования. Он создает для СУБД виртуальный объектный интерфейс.

ORM помогает программистам избавиться от больших кусков кода, ошибок и повышает скорость разработки. То есть, мы избавляемся от обычных SQL запросов, пишем небольшие куски кодов в объектно-ориентированным стилем, а библиотека транслирует этот код в sql запросы.

Сейчас есть довольно большое количество ORM библиотек для различных языков. Например, для PHP это Propel, Doctrine и Qcodo. Для Python это SQLAlchemy, Storm. Для Java это Hibernate. Для всех популярных объектно-ориентированных языков есть по крайней мере один свой ORM.

После того, как с помощью языка JavaScript (Node.js) стало возможно программировать на сервере, и для этого языка появились ORM системы. Самый популярный из них — это Sequelize. Как понимаете, в этом уроке мы будем изучать его.

Node.js и ORM-система Sequelize — Начинаем работать

Библиотека Sequelize — это Node.js ORM система для работы с такими базами данных, как PostgreSQL, MySQL, SQLite и MSSQL. Давайте начнем работать с Sequelize. Нам нужно установить данную библиотеку. Для установки открываем терминал (командная строка) и вводим команду ниже.

После этого нужно установить одну из библиотек. Например, если вы хотите работать с MySQL, то нужно установить mysql2.

Настройка соединения

После установки библиотек мы можем установить соединение с базой данных.

Давайте немного подробнее рассмотрим этот код. После подключение ORM-системы Sequelize, нам в первом строке кода вернется функция / конструктор. Конструктор принимает несколько аргументов. Во второй строке кода мы вызываем конструктор (создаем новый объект с помощью оператора new), и передаем нужные аргументы / параметры.

Первые три аргументы — это данные доступа к базе данных:

Последним аргументом конструктор принимает объект, где в виде key-value указаны необходимые параметры.

Пример кода, который указан выше, это общий пример, поэтому предлагаю рассмотреть конкретный пример. Например, давайте подключимся к базе данных MySQL.

В константе (переменная) sequelize содержится экземпляр соединения и мы можем с ним работать. Sequelize имеет функцию (метод) authenticate, с помощью которого можно проверить состояние соединение.

Источник

Опасная уязвимость в популярной библиотеке Sequelize

orm sequelize что это. Смотреть фото orm sequelize что это. Смотреть картинку orm sequelize что это. Картинка про orm sequelize что это. Фото orm sequelize что это

Привет, Хабр! Данная статья будет интересна тем, кто уже использует библиотеку Sequelize или же только собирается с ней работать. Под катом мы расскажем, чем встроенный функционал operatorAliases может быть вреден и как избежать утечки из собственной базы данных.

Что такое Sequelize, где он используется и для чего?

Sequelize — это ORM-библиотека на Node.js для Postgres, MySQL, MariaDB, SQLite и Microsoft SQL Server, которая осуществляет сопоставление таблиц в бд и отношений между ними с классами. При использовании Sequelize мы можем не писать SQL-запросы, а должны работать с данными как с обычными объектами. Она имеет надежную поддержку транзакций, отношения, активную и отложенную загрузку, репликацию чтения и многое другое.

Что за опция operatorAliases, и в чем заключается ее опасность?

По умолчанию Sequelize использует операторы символов. Использование Sequelize без символьных псевдонимов, конечно, повышает безопасность. И хотя отсутствие строковых псевдонимов делает инъекцию операторов крайне маловероятной, мы всегда должны корректно проверять и очищать данные, вводимые пользователем.

А сама опция operatorAliases позволяет установить, будут ли доступны операторы-псевдонимы. Вот как выглядит пример активации в коде:

orm sequelize что это. Смотреть фото orm sequelize что это. Смотреть картинку orm sequelize что это. Картинка про orm sequelize что это. Фото orm sequelize что это

Когда все работает правильно

Рассмотрим код демо-приложения. Файл модели user.model.js содержит:

orm sequelize что это. Смотреть фото orm sequelize что это. Смотреть картинку orm sequelize что это. Картинка про orm sequelize что это. Фото orm sequelize что это

Видно, что в таблице пользователей есть три поля, и они все имеют строковой тип данных.

Файл контроллера auth.controller.js содержит:

orm sequelize что это. Смотреть фото orm sequelize что это. Смотреть картинку orm sequelize что это. Картинка про orm sequelize что это. Фото orm sequelize что это

В коде используется метод findOne к модели User. И метод findOne возвращает первую строку из базы данных, согласно переданному условию запроса. В данном случае, приложение получает от пользователя данные username и password, применяет их в запрос к таблице users.

Сгенерированный в данном случае запрос будет выглядеть примерно так:
SELECT `id`, `username`, `email`, `password`, `createdAt`, `updatedAt` FROM `users` AS `users` WHERE `users`.`username` = :username AND `users`.`password` = :password LIMIT 1;

Поскольку используется ORM для формирования запросов, банальная SQL-инъекция не сработает. Если в базе не найдется совпадений по пользователю, приложение вернет ошибку User Not found. В случае совпадений вводных данных на уровне базы данных приложение сравнит введенный пароль с паролем, хранящимся в базе, и либо вернет ошибку «Invalid Password!» при несовпадении, либо токен авторизации в случае успеха. Алгоритм проверки вводных данных выбран специально для тестирования уязвимости.

Таблица будет содержать такие данные:

orm sequelize что это. Смотреть фото orm sequelize что это. Смотреть картинку orm sequelize что это. Картинка про orm sequelize что это. Фото orm sequelize что это
orm sequelize что это. Смотреть фото orm sequelize что это. Смотреть картинку orm sequelize что это. Картинка про orm sequelize что это. Фото orm sequelize что это
orm sequelize что это. Смотреть фото orm sequelize что это. Смотреть картинку orm sequelize что это. Картинка про orm sequelize что это. Фото orm sequelize что это

Авторизация работает исправно.

А что же с операторами и псевдонимами?

orm sequelize что это. Смотреть фото orm sequelize что это. Смотреть картинку orm sequelize что это. Картинка про orm sequelize что это. Фото orm sequelize что это
orm sequelize что это. Смотреть фото orm sequelize что это. Смотреть картинку orm sequelize что это. Картинка про orm sequelize что это. Фото orm sequelize что это

Псевдонимы обозначаются символом “$”, синтаксис псевдонимов схож с MongoDB. Нам доступны операторы поиска, сравнения и многие другие. Не смотря на строгую типизацию данных в модели, передача данных от пользователя в ORM в формате JSON влечет за собой нормализацию. И тут начинается самое интересное!

Когда беда стучится в DOM

Групповая атака (Batching attack)

orm sequelize что это. Смотреть фото orm sequelize что это. Смотреть картинку orm sequelize что это. Картинка про orm sequelize что это. Фото orm sequelize что это

Такого вида запрос к приложению инициирует запрос к базе:
Executing (default): SELECT `id`, `username`, `email`, `password`, `createdAt`, `updatedAt` FROM `users` AS `users` WHERE `users`.`username` IN (‘admin’, ‘more’, ‘much more’) AND `users`.`password` = ‘wrong pass’ LIMIT 1;

При помощи этой атаки можно за один запрос к серверу проверить на валидность много логинов на конкретный пароль и наоборот. Атака работает в последней на декабрь 2020 версии библиотеки (6.3.5) и при выключенной опции operatorsAliases.

Атака преобразования типов данных

Если передать приложению данные вида…

orm sequelize что это. Смотреть фото orm sequelize что это. Смотреть картинку orm sequelize что это. Картинка про orm sequelize что это. Фото orm sequelize что это

… то, ничего в нашем случае не произойдет. Логическое условие в базу данных хоть и будет правильным, проверка пароля в исследуемом приложении на уровне приложения и сравнение разных типов данных не может вернуть true.

Атака при помощи операторов сравнения

orm sequelize что это. Смотреть фото orm sequelize что это. Смотреть картинку orm sequelize что это. Картинка про orm sequelize что это. Фото orm sequelize что это

База данных возвращает данные, так как есть совпадение username = admin и пароля, не равного “aaa”. Для того чтобы пройти процесс авторизации полностью, нам необходимо достать пароль.

Атака операторов регулярных выражений и поиска в строке

orm sequelize что это. Смотреть фото orm sequelize что это. Смотреть картинку orm sequelize что это. Картинка про orm sequelize что это. Фото orm sequelize что это

Когда символ не сойдется, возникнет ошибка, что пользователь не найден.

orm sequelize что это. Смотреть фото orm sequelize что это. Смотреть картинку orm sequelize что это. Картинка про orm sequelize что это. Фото orm sequelize что это

Если символ сойдется, будет ошибка о неверном пароле. В базу выполняется запрос вида:
SELECT `id`, `username`, `email`, `password`, `createdAt`, `updatedAt` FROM `users` AS `users` WHERE `users`.`username` = ‘admin’ AND `users`.`password` LIKE ‘E%’ LIMIT 1;

Таким образом, посимвольно можно восстановить данные из таблицы.

Атака сравнения столбцов в таблице

orm sequelize что это. Смотреть фото orm sequelize что это. Смотреть картинку orm sequelize что это. Картинка про orm sequelize что это. Фото orm sequelize что это

Запрос в базу будет:
SELECT `id`, `username`, `email`, `password`, `createdAt`, `updatedAt` FROM `users` AS `users` WHERE `users`.`username` = ‘admin’ AND `users`.`password` = `aaaaa` LIMIT 1;

orm sequelize что это. Смотреть фото orm sequelize что это. Смотреть картинку orm sequelize что это. Картинка про orm sequelize что это. Фото orm sequelize что это

Выполнит в базу следующий запрос:
SELECT `id`, `username`, `email`, `password`, `createdAt`, `updatedAt` FROM `users` AS `users` WHERE `users`.`username` = ‘admin’ AND `users`.`password` = `password` LIMIT 1;
Тем самым выполнив логическое условие на уровне базы данных.

Источник

Идеальный инструмент для работы с СУБД без SQL для Node.js или Все, что вы хотели знать о Sequelize. Часть 2

orm sequelize что это. Смотреть фото orm sequelize что это. Смотреть картинку orm sequelize что это. Картинка про orm sequelize что это. Фото orm sequelize что это

Это вторая из 3 частей руководства, в которой мы поговорим о простых и продвинутых ассоциациях (отношениях между моделями), «параноике», нетерпеливой и ленивой загрузке, а также о многом другом.

Я постараюсь быть максимально лаконичным (надеюсь, без ущерба для полноты изложения материала). Я также постараюсь излагать материал максимально простым языком. Большинство примеров, приводимых в руководстве, заимствованы из официальной документации.

Содержание

Ассоциации

Sequelize поддерживает стандартные ассоциации или отношения между моделями: один-к-одному (One-To-One), один-ко-многим (One-To-Many), многие-ко-многим (Many-To-Many).

Существует 4 типа ассоциаций:

Определение ассоциации

Все эти функции принимают объект с настройками (для первых трех он является опциональным, для последнего — обязательным). В настройках должно быть определено как минимум свойство through :

Порядок определения ассоциаций имеет принципиальное значение. В приведенных примерах A — это модель-источник (source), а B — это целевая модель (target). Запомните эти термины.

A.hasOne(B) означает, что между A и B существуют отношения один-к-одному, при этом, внешний ключ (foreign key) определяется в целевой модели ( B ).

A.belongsTo(B) — отношения один-к-одному, внешний ключ определяется в источнике ( A ).

A.hasMany(B) — отношения один-ко-многим, внешний ключ определяется в целевой модели ( B ).

В этих случаях Sequelize автоматически добавляет внешние ключи (при их отсутствии) в соответствующие модели (таблицы).

A.belongsToMany(B, < through: 'C' >) означает, что между A и B существуют отношения многие-ко-многим, таблица C выступает в роли связующего звена между ними через внешние ключи (например, aId и bId ). Sequelize автоматически создает модель C при ее отсутствии, определяя в ней соответствующие ключи.

Определение стандартных отношений

Как правило, ассоциации используются парами:

Один-к-одному

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

Дальнейший вызов Bar.sync() приведет к отправке в БД следующего запроса:

При создании ассоциации могут использоваться некоторые настройки.

Пример кастомизации поведения при удалении и обновлении внешнего ключа:

В случае кастомизации внешнего ключа с помощью объекта, можно определять его тип, значение по умолчанию, ограничения и т.д. Например, в качестве типа внешнего ключа можно использовать DataTypes.UUID вместо дефолтного INTEGER :

Один-ко-многим

Обратите внимание: в данном случае вопрос о том, в какой из двух таблиц должен быть определен внешний ключ не является актуальным, поскольку такой ключ может быть определен только в целевой модели.

В данном случае в БД будет отправлен такой запрос:

Как и в случае с отношениями один-к-одному, рассматриваемую ассоциацию можно настраивать различными способами.

Многие-ко-многим

Обратите внимание: в отличие от первых двух ассоциаций, внешний ключ не может быть определен ни в одной из связанных таблиц. Для этого используется так называемая «соединительная таблица» (junction, join, through table).

Как упоминалось ранее, Sequelize создает соединительную таблицу автоматически. Но мы вполне можем сделать это самостоятельно:

В этом случае в БД будет отправлен такой запрос:

Выполнение запросов, включающих ассоциации

Немедленная загрузка и отложенная загрузка

«Ленивая» (lazy) или отложенная загрузка позволяет получать ассоциации (т.е. связанные экземпляры) по мере необходимости, а «нетерпеливая» (eager) или немедленная загрузка предполагает получение всех ассоциаций сразу при выполнении запроса.

Пример ленивой загрузки

В данном случае мы выполняем два запроса — корабль запрашивается при необходимости. Это позволяет сэкономить время и память. Обратите внимание: метод getShip() был создан автоматически, автоматически создаются и другие методы (см. ниже).

Пример нетерпеливой загрузки

Создание, обновление и удаление ассоциаций

Для создания, обновления и удаления ассоциаций можно использовать как обычные запросы:

так и специальные методы/миксины (микшины, примеси, mixins) (см. ниже).

Синонимы ассоциаций и кастомные внешние ключи

Немного упростим пример с кораблями и капитанами:

Вызов Ship.belongsTo(Captain) приводит к автоматическому созданию внешнего ключа и «геттеров»:

Название внешнего ключа может быть указано при определении ассоциации:

Внешний ключ также может быть определен в виде синонима:

Ничто не мешает нам использовать оба способа определения внешних ключей одновременно:

Специальные методы/миксины

Foo.hasOne(Bar)

Foo.belongsTo(Bar)

Foo.hasMany

Геттеры принимают такие же настройки, что и обычные поисковые методы (такие как findAll() ):

Foo.belongsToMany(Bar, < through: Baz >)

Для формирования названий методов вместо названия модели может использоваться синоним, например:

Обратите внимание: как было отмечено ранее, ассоциации определяются в паре. Это объясняется тем, что обе модели должны знать о существовании ассоциации между ними.

Синонимы позволяют определять несколько ассоциаций между одними и теми же моделями:

Создание ассоциаций с помощью полей, которые не являются первичными ключами

В качестве внешних ключей могут использоваться не только основные ключи, но и другие поля. Единственным требованием к полю, используемому в качестве внешнего ключа, является то, что его значение должно быть уникальным, в противном случае, это не будет иметь смысла.

belongsTo()

Ассоциация A.belongsTo(B) приводит к созданию внешнего ключа в модели-источнике ( A ).

Снова вернемся к примеру с кораблями и ограничим уникальность имен капитанов:

После этого мы можем делать так:

hasOne() и hasMany()

В данном случае вместо targetKey определяется настройка sourceKey :

belongsToMany()

В данном случае необходимо определить два внешних ключа в соединительной таблице.

Далее выполняется один из следующих 4 шагов:

Еще раз в качестве напоминания:

«Параноик»

Sequelize поддерживает создание так называемых «параноидальных» (paranoid) таблиц. Из таких таблиц данные по-настоящему не удаляются. Вместо этого, в них добавляется колонка deletedAt в момент выполнения запроса на удаление. Это означает, что в таких таблицах выполняется мягкое удаление (soft-deletion).

При вызове метода destroy() производится мягкое удаление:

Для окончательного удаления параноика следует использовать настройку force: true :

Для восстановления «удаленного» значения используется метод restore() :

Для учета «удаленных» записей при выполнении запроса используется настройка paranoid: false :

Нетерпеливая загрузка

Нетерпеливая загрузка — это одновременная загрузка основной и связанных с ней моделей. На уровне SQL это означает одно или более соединение (join).

В дальнейших примерах будут использоваться следующие модели:

Получение одного связанного экземпляра

Получение всех связанных экземпляров

Получение ассоциации через синоним

Существуют и другие способы получения ассоциаций через синонимы:

Фильтрация с помощью нетерпеливой загрузки

Фильтрация на уровне связанной модели

Генерируемый SQL-запрос выглядит так:

В следующем примере настройка where применяется для фильтрации значений связанной модели с помощью функции Sequelize.col() :

Сложная фильтрация с помощью where на верхнем уровне

Генерируемый SQL-запрос выглядит так:

При этом, уровень вложенности фильтруемых колонок значения не имеет.

include может принимать массив связанных моделей:

Нетерпеливая загрузка в случае с отношениями многие-ко-многим

В данном случае Sequelize автоматически добавляет соединительную таблицу:

Настройка attributes позволяет определять включаемые в ответ поля соединительной таблицы:

В случае, когда нам не нужны такие поля, в attributes передается пустой массив:

Включаемые поля соединительной таблицы можно фильтровать с помощью настройки where :

Генерируемый SQL-запрос ( sqlite ):

Для включения всех связанных моделей используются настройки all и nested :

Сортировка связанных экземпляров при нетерпеливой загрузке

Для сортировки связанных экземпляров используется настройка order (на верхнем уровне):

В случае с отношениями многие-ко-многим, у нас имеется возможность выполнять сортировку по атрибутам соединительной таблицы. Предположим, что между моделями Division и Department существуют такие отношения, а соединительная таблица между ними называется DepartmentDivision :

Вложенная нетерпеливая загрузка

Вложенная нетерпеливая загрузка может использоваться для загрузки всех связанных экземпляров связанного экземпляра:

Данный запрос выполняет внешнее соединение ( OUTER JOIN ). Применение настройки where к связанной модели произведет внутреннее соединение ( INNER JOIN ) — будут возвращены только экземпляры, которые имеют совпадающие подмодели. Для получения всех родительских экземпляров используется настройка required: false :

Создание экземпляров с ассоциациями

Экземпляр может быть создан сразу с вложенной ассоциацией. Однако, выполнение обновлений и удалений вложенных объектов в настоящее время не поддерживается.

Последний пример может быть расширен для поддержки ассоциаций:

Имеется возможность связать продукт с несколькими тегами. Соответствующая настройка может выглядеть так:

Теперь создадим продукт с несколькими тегами:

И с поддержкой синонимов:

Продвинутые ассоциации M:N

Начнем с создания ассоциации многие-ко-многим между моделями User и Profile :

Определение соединительной таблицы самостоятельно имеет некоторые преимущества по сравнению с ее автоматической генерацией. Мы, например, можем определять дополнительные атрибуты в такой таблице:

После этого мы можем получать дооплнительную информацию из соединительной таблицы. Например, при вызове user.addProfile() мы можем передавать значения для дополнительной колонки с помощью настройки through :

Также вместо уникального, в соединительной таблице можно определить первичный ключ:

Ассоциация «супер многие-ко-многим»

Наши модели будут выглядеть так:

Определяем отношения многие-ко-многим между моделями User и Profile через модель Grant :

Что если вместо определения отношения многие-ко-многим мы сделаем так?

Это показывает, что отношения многие-ко-многим не сильно отличаются от двух ассоциаций один-ко-многим. Единственным отличием между ними является то, как будет работать нетерпеливая загрузка:

На самом деле, для успешного выполнения всех указанных выше операций достаточно скомбинировать оба подхода:

Это позволяет выполнять все виды вложенных включений:

Синонимы и кастомные названия для ключей

В случае с ассоциацией многие-ко-многим синонимы определяются следующим образом:

Вот как выглядит SQL-запрос на создание таблицы product_categories :

Обратите внимание: настройки foreignKey и otherKey должны определяться в обоих вызовах. Если определить их только в одном вызове, поведение Sequelize будет непредсказуемым.

Sequelize также поддерживает циклические отношения многие-ко-многим:

Определение возвращаемых атрибутов соединительной таблицы

По умолчанию при нетерпеливой загрузке в случае с ассоциацией многие-ко-многим возвращается такой объект ( User.findOne(< include: Profile >) ):

Для того, чтобы получить только некоторые поля из соединительной таблицы используется настройка attributes :

При использовании миксинов (например, user.getProfiles() ), вместо методов для поиска (например, User.findAll() ), для фильтрации полей соединительной таблицы используется настройка joinTableAttributes :

Ассоциация многие-ко-многим-ко-многим и т.д.

Предположим, что мы моделируем игру. У нас есть игроки и команды. Команды играют в игры. Игроки могут менять команды в середине чемпионата (но не в середине игры). В одной игре участвует две команды, в каждой команде имеется свой набор игроков (для текущей игры).

Начнем с определения соответствующих моделей:

Вопрос: как определить ассоциацию между этими моделями?

Первое, что можно заметить:

Это означает, что между моделями Game и Team должны существовать отношения многие-ко-многим. Реализуем супер-вариант названной ассоциации (как в предыдущем примере):

Для обеспечения максимальной гибкости снова прибегнем к супер-версии M:N:

Эта ассоциация делает именно то, что мы хотим.

Полный пример выглядит так:

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

Благодарю за внимание и хорошего дня!

Аренда облачного сервера с быстрыми NVMе-дисками и посуточной оплатой у хостинга Маклауд.

Источник

Идеальный инструмент для работы с СУБД без SQL для Node.js или Все, что вы хотели знать о Sequelize. Часть 3

orm sequelize что это. Смотреть фото orm sequelize что это. Смотреть картинку orm sequelize что это. Картинка про orm sequelize что это. Фото orm sequelize что это

Доброго времени суток, друзья!

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

Я постараюсь быть максимально лаконичным (надеюсь, без ущерба для полноты изложения материала). Я также постараюсь излагать материал максимально простым языком. Большинство примеров, приводимых в руководстве, заимствованы из официальной документации.

Содержание

Область видимости ассоциаций

Область видимости ассоциаций (assosiation scopes) похожа на области видимости моделей в том, что обе автоматически применяют к запросам такие вещи, как предложение where ; разница между ними состоит в том, что область модели применяется к вызовам статических методов для поиска, а область ассоциации — к вызовам поисковых методов экземпляра (таким как миксины).

Пример применения области ассоциации для отношений один-ко-многим:

Последний вызов приводит к генерации такого запроса:

На самом деле, мы можем добиться такого же поведения с помощью стандартной области видимости:

После этого, вызов foo.getOpenBars() вернет аналогичный результат.

Полиморфные ассоциации

Полиморфная ассоциация (polymorphic assosiation) состоит из двух и более ассоциаций, взаимодействующих с одним внешним ключом.

Перед настройкой такой ассоциации, рассмотрим пример ее использования:

Создание полиассоциации один-ко-многим

Для настройки полиассоциации для приведенного выше примера (полиассоциации один-ко-многим) необходимо выполнить следующие шаги:

Обратите внимание на следующее:

Эти области автоматически применяются при использовании ассоциативных функций. Несколько примеров:

Полиморфная ленивая загрузка

Обратите внимание, что приведенная выше реализация getCommentable() :

Полиморфная нетерпеливая загрузка

Теперь мы хотим выполнить полиморфную нетерпеливую загрузку связанных commentable для одного (или более) комментария:

Решение состоит во включении Image и Video для того, чтобы хук afterFind() мог автоматически добавить поле commentable в экземпляр.

Настройка полиассоциации многие-ко-многим

Для настройки рассматриваемой полиассоциации необходимо выполнить следующие шаги:

Применение области ассоциации к целевой модели

Область ассоциации может применяться не только к соединительной таблице, но и к целевой модели.

После этого, вызов image.getPendingTags() приведет к генерации такого запроса:

Мы видим, что обе области были автоматически применены:

Транзакции

Sequelize поддерживает выполнение двух видов транзакций:

Неуправляемые транзакции

Управляемые тразакции

Для выполнения управляемой транзакции в sequelize.transaction() передается функция обратного вызова. Далее происходит следующее:

Таким образом, sequelize.transaction() либо разрешается с результатом, возвращаемым колбэком, либо отклоняется с ошибкой.

Автоматическая передача транзакции во все запросы

В приведенных примерах транзакция передавалась вручную — < transaction: t >. Для автоматической передачи транзакции во все запросы необходимо установить модуль cls-hooked (CLS — Continuation Local Storage, «длящееся» локальное хранилище) и инстанцировать пространство имен (namespace):

Затем следует использовать это пространство имен следующим образом:

Обратите внимание: мы вызываем метод useCLS() на конструкторе, а не на экземпляре. Это означает, что пространство имен будет доступно всем экземплярам, а также, что CLS — это «все или ничего», нельзя включить его только для некоторых экземпляров.

В большинстве случаев, в явном вызове namespace.get(‘transaction’) нет необходимости, поскольку все запросы автоматически получают транзакцию из пространства имен:

Параллельные/частичные транзакции

С помощью последовательности запросов можно выполнять параллельные транзакции. Также имеется возможность исключать запросы из транзакции. Для управления тем, каким транзакциям принадлежит запрос, используется настройка transaction (обратите внимание: SQLite не поддерживает одновременное выполнение более одной транзакции).

Уровни изоляции

Возможные уровни изоляции при запуске транзакции:

По умолчанию Sequelize использует уровень изоляции БД. Для изменения уровня изоляции используется настройка isolationLevel :

Или на уровне всего приложения:

Использование транзакции совместно с другими методами

Обычно, transaction передается в метод вместе с другими настройками в качестве первого аргумента.

Хук afterCommit()

Объект transaction позволяет регистрировать фиксацию изменений. Хук afterCommit() может быть добавлен как к управляемым, так и к неуправляемым объектам транзакции:

Обратите внимание на следующее:

Хук afterCommit() можно использовать в дополнение к хукам модели для определения момента сохранения экземпляра и его доступности за пределами транзакции:

Обратите внимание: хуки могут использоваться только на уровне моделей.

Доступные хуки

Sequelize предоставляет большое количество хуков. Их полный список можно найти здесь. Порядок вызова наиболее распространенных хуков следующий:

Определение хуков

Аргументы в хуки передаются по ссылкам. Это означает, что мы можем модифицировать значения и это отразится на соответствующих инструкциях. Хук может содержать асинхронные операции — в этом случае функция должна возвращать промис.

Существует три способа программного добавления хуков:

Обратите внимание, что удаляться могут только именованные хуки:

Глобальные/универсальные хуки

Глобальными называются хуки, которые выполняются для всех моделей. Особенно полезными такие хуки являются в плагинах. Они определяются двумя способами:

Хуки, связанные с подключением к БД

Существует 4 хука, выполняемые до и после подключения к БД и отключения от нее:

Эти хуки могут использоваться для асинхронного получения полномочий (credentials) для доступа к БД или получения прямого доступа к низкоуровневому соединению с БД после его установки.

Например, мы можем асинхронно получить пароль от БД из хранилища токенов и модифицировать объект с настройками:

Рассматриваемые хуки могут быть определены только как глобальные, поскольку соединение является общим для всех моделей.

Хуки экземпляров

Следующие хуки будут запускаться при редактировании единичного объекта:

Хуки моделей

Хуки и ассоциации

Один-к-одному и один-ко-многим

По умолчанию Sequelize пытается максимально оптимизировать запросы. Например, при вызове каскадного удаления Sequelize выполняет:

Однако, добавление hooks: true отключает оптимизации. В этом случае Sequelize сначала выполняет выборку связанных объектов с помощью SELECT и затем уничтожает каждый экземпляр по одному для обеспечения вызова соответствующих хуков с правильными параметрами.

Хуки и транзакции

Если в оригинальном вызове была определена транзакция, она будет передана в хук вместе с другими настройками:

Интерфейс запросов

Каждый экземпляр использует интерфейс запросов (query interface) для взаимодействия с БД. Методы этого интерфейса являются низкоуровневыми в сравнении с обычными методами. Но, разумеется, по сравнению с запросами SQL, они являются высокоуровневыми.

Рассмотрим несколько примеров использования методов названного интерфейса (полный список методов можно найти здесь).

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *