Выпущена новая основная версия TypeScript ORM, ознакомьтесь с ее новыми функциями и критическими изменениями.

Если вы не знаете…

Если вы никогда не слышали о MikroORM, это ORM-преобразователь данных TypeScript с Unit of Work и Identity Map. В настоящее время он поддерживает драйверы MongoDB, MySQL, PostgreSQL и SQLite. Ключевые особенности ORM:

Вы можете прочитать полную вводную статью здесь или просмотреть документацию.

Встроенный Knex.js

Вы, вероятно, уже знаете Knex.js, но если вы этого не сделаете, это построитель SQL-запросов с батарейками для Postgres, MSSQL, MySQL , MariaDB, SQLite3, Oracle и Amazon Redshift, обеспечивающие гибкость, переносимость и удобство использования использовать.

Knex.js теперь используется как конструктор запросов и как средство выполнения запросов для всех драйверов SQL. Это позволяет упростить реализацию драйверов SQL, а также открывает некоторые новые возможности.

Использование Knex.js

Вы можете получить доступ к сконфигурированному экземпляру knex с помощью метода qb.getKnexQuery(). Затем вы можете выполнить его с помощью Connection.execute() и сопоставить результаты с помощью EntityManager.map().

Вы также можете получить чистый и настроенный экземпляр knex из соединения с помощью метода getKnex(). Поскольку этот метод недоступен в базовом классе Connection, вам нужно будет либо вручную ввести приведение соединения к AbstractSqlConnection (или фактическую реализацию, которую вы используете, например MySqlConnection), либо предоставить правильный тип драйвера для вашего экземпляра EntityManager, который будет затем автоматически выводится в em.getConnection() методе.

Реализации драйверов и соединений не экспортируются напрямую из модуля mikro-orm. Вы можете импортировать их из mikro-orm/dist (например, import { PostgreSqlDriver } from 'mikro-orm/dist/drivers/PostgreSqlDriver').

Пул соединений

Благодаря тому, что Knex.js используется в качестве обработчика запросов, наконец-то стала доступна поддержка пула соединений. Tarn.js используется для этого внутри, используя пул соединений с min: 2, max: 10 для библиотек MySQL и PG и одно соединение для sqlite3 по умолчанию. Используйте параметр pool, чтобы изменить это при инициализации ORM.

Еще драйверы SQL?

Одной из самых веских причин для интеграции Knex.js было то, что он позволяет упростить и унифицировать драйверы SQL и открывает двери для внедрения новых драйверов SQL. Knex.js в настоящее время поддерживает (кроме тех, которые в настоящее время поддерживаются MikroORM): MSSQL, Oracle и Amazon Redshift.

Благодаря классам AbstractSqlDriver и AbstractSqlConnection их должно быть довольно просто реализовать. Я открыт для PR для этих драйверов, так как я хотел бы сосредоточиться в основном на разработке новых функций ORM вместо изучения новых диалектов SQL, которые я никогда не использовал. Я буду рад помочь всем, кто заинтересован - не стесняйтесь обращаться ко мне через Slack, электронную почту или GitHub.

Упрощенное определение сущности

Теперь больше не нужно объединять сущности с IEntity интерфейсом, который загрязнял интерфейс сущности внутренними методами. Введены новые интерфейсы IdentifiedEntity<T>, UuidEntity<T> и MongoEntity<T>, которые должны быть реализованы сущностями. Они не добавляют никаких новых свойств или методов, поддерживая чистоту интерфейса объекта.

Интерфейс IEntity был переименован в AnyEntity<T, PK>, и у него больше нет общедоступных методов, таких как toJSON(), toObject() или init(). Можно использовать метод wrap(), предоставленный ORM, который при необходимости улучшит тип свойства с помощью этих методов (например, await wrap(book.author).init()). Чтобы все методы были доступны для объекта, вы все равно можете использовать слияние интерфейсов с WrappedEntity<T, PK>, которое расширяет AnyEntity<T, PK> и определяет все эти методы.

Вам нужно будет пометить объект, реализовав один из *Entity интерфейсов:

  • IdEntity<T> для числового / строкового PK в свойстве id (id: number)
  • UuidEntity<T> для строки PK на свойстве uuid (uuid: string)
  • MongoEntity<T> для монго, где id: string и _id: ObjectId обязательны
  • AnyEntity<T, PK> для других возможных свойств (введите имя свойства PK в параметр PK, например: AnyEntity<Book, 'myPrimaryProperty'>')

Чтобы сохранить все общедоступные методы, которые были частью интерфейса IEntity в v2, вы можете использовать WrappedEntity<T, PK> через слияние интерфейсов.

Вложенные запросы

Драйвер SQL теперь поддерживает вложенные where и orderBy условия. Это означает, что вы можете запрашивать свойства отношения, и отношение будет автоматически соединено для вас. Они доступны как в EntityManager, так и в QueryBuilder API.

Строгий набор запросов

Раньше параметр where методов поиска EntityManager (find(), findOne(), count()) был слабо типизирован. Это позволяло пользователям передавать туда практически все, что угодно.

Теперь запрос строго типизирован, можно использовать только свойства сущности и операторы, а также проверяется тип значения свойства.

Улучшенный генератор схем

SchemaGenerator теперь поддерживает создание, обновление и удаление схемы. Вы можете получить SQL-запросы в виде массива строк или напрямую запустить их в базе данных.

Всегда сначала проверяйте сгенерированный SQL перед его запуском.

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

Миграции

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

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

Создание сущностей из текущей базы данных

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

Он поддерживает базовое определение сущности, включая отношения ManyToOne и OneToOne. В настоящее время ManyToMany будет сгенерирован как дополнительная сущность с двумя отношениями ManyToOne, и вам нужно будет провести рефакторинг самостоятельно.

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

CLI

Хотя вы можете использовать SchemaGenerator и EntityGenerator вручную, гораздо проще использовать новый инструмент CLI. Просто создайте файл конфигурации в корневом каталоге или добавьте его путь к package.json. Файлы TypeScript также поддерживаются через ts-node:

Теперь вы можете использовать CLI с помощью npx:

Чтобы проверить свою настройку, вы можете использовать команду mikro-orm debug. После того, как вы правильно настроили его, вы также можете повторно использовать его при инициализации ORM:

// when no options parameter is provided, CLI config will be used
const orm = await MikroORM.init();

Пользовательские типы сопоставления

С помощью Custom Types мы теперь можем улучшить то, как значение базы данных будет представлено в ORM. Вы можете определить собственные типы, расширив абстрактный класс Type, у него есть 4 дополнительных метода:

  • convertToDatabaseValue(value: any, platform: Platform): any

Преобразует значение из его JS-представления в его представление в базе данных этого типа. По умолчанию возвращает без изменений value.

  • convertToJSValue(value: any, platform: Platform): any

Преобразует значение из его представления в базе данных в его JS-представление этого типа. По умолчанию возвращает без изменений value.

  • toJSON(value: any, platform: Platform): any

Преобразует значение из его JS-представления в его сериализованную форму JSON этого типа. По умолчанию преобразуется в значение базы данных.

  • getColumnType(prop: EntityProperty, platform: Platform): string

Получает фрагмент объявления SQL для поля этого типа. По умолчанию возвращает columnType данного свойства.

Вот упрощенная версия DateType, которая уже присутствует в ORM:

И многое другое…

Есть еще много новых функций, см. Журнал изменений, чтобы прочитать полный список. Вот некоторые из них, о которых стоит упомянуть:

Заметные критические изменения

Вот краткий список критических изменений. Вы можете увидеть полный список в документации: https://mikro-orm.io/docs/upgrading-v2-to-v3/.

Автоматическая очистка отключена по умолчанию

Если раньше в вашей конфигурации ORM было autoFlush: false, теперь вы можете удалить эту строку, никаких изменений в вашем приложении не требуется.

Значение по умолчанию для autoFlush теперь false. Это означает, что вам нужно вызвать em.flush() себя, чтобы сохранить изменения в базе данных. Вы все равно можете изменить это с помощью опций ORM, чтобы упростить переход, но обычно это не рекомендуется, так как это может вызвать нежелательные небольшие транзакции, создаваемые вокруг каждого persist.

API транзакций

Транзакции теперь требуют использования em.transactional() метода, предыдущие методы _82 _ / _ 83 _ / _ 84_ теперь удалены.

Сделаем его немного более профессиональным…

Ничего особенного, но, вероятно, стоит упомянуть - репозиторий MikroORM был перенесен в новую MikroORM GitHub Organization, а сайт теперь перемещен в mikro-orm.io. Старые ссылки должны быть правильно перенаправлены, если вы найдете 404, сообщите мне о проблемах с GitHub!

Веб-сайт также был переработан - теперь он построен на Docusaurus (v2) и обеспечивает полнотекстовый поиск с помощью Algolia. Документы теперь тоже версированы.

Зацени!

Что дальше?

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

  • Составные первичные ключи
  • Транзакции в MongoDB
  • Комплексная гидратация объединенных наборов результатов
  • Журнал медленных запросов
  • Поддержка M: N в генераторе сущностей

Есть еще несколько интересных предложений в вопросах Github, например, Dataloader integration.

WDYT?

Итак, это MikroORM 3, что вы о нем думаете? Какие функции или изменения вы хотели бы увидеть дальше? Или какую часть документации нужно улучшить и как?

Нравится МикроОРМ? ⭐️ Пометьте на GitHub и поделитесь этой статьей со своими друзьями.