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

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

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

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

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

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

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

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

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

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

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

В коде используется метод 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!» при несовпадении, либо токен авторизации в случае успеха. Алгоритм проверки вводных данных выбран специально для тестирования уязвимости.

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



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

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


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

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

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

Такого вида запрос к приложению инициирует запрос к базе:
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.

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

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

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

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

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

Читайте также:  мендебаев данияр азылханович биография

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

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

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

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

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

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

Выполнит в базу следующий запрос:
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

Это вторая из 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

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

Читайте также:  roberto rossi что за бренд

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

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

Содержание

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

Область видимости ассоциаций (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, они являются высокоуровневыми.

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

Источник

Обучающий онлайн портал