Выбор ORM для Котлина

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

Обычно люди как-то не особенно задумываются – ну есть JPA и есть, его все используют. Ну, бывают проблемы, так у всех они. А если сделать несколько шагов назад и посмотреть на картину в целом?

JPA

JPA по сути стандартизация Hibernate. Понятно, что со временем появились альтернативные реализации (EclipseLink прежде всего – в надежде на то, что просто разработчики Hibernate не очень и не осилили фичи, а все-таки их можно сделать качественно), но саму концепцию это не меняет.

Идея JPA в том, что мы можем так описать классы, что из JPA-запроса можно будет получать сразу дерево объектов, а потом иметь возможность дозагружать данные, менять и сохранять данные. Для этого простого создания экземпляров классов недостаточно, нужно делать магию с прокси-классами и менеджерами объектов, которые отлавливают изменения и дозагружают/сохраняют. И тут начинаются различные “интересные” side effects.

Таким образом мы скрываем реляционную сущность БД и SQL. Понятно, что при таком подходе достаточно просто неэффективно написать запрос, т.к. далеко не очевидно как он будет выполняться. Сложнее работать, т.к. у нас 4 API: базовый программный API, Criteria API, HQL (Hibernate Query Language)/JPQL(Java Persistence Query Language ), SQL. В сложных вариантах нужно обращаться к SQL, но т.к. 99% времени с ним работы нет, то это программистам сложно. Просто из-за переключения на другой язык с кучей своих особенностей.

Обертки JPA

Позже появились обертки над JPA – Spring Data и Panache. Их идея проста – давайте не будем использовать все те сложные штуки из JPA. Сконцентрируемся на работе с одним классом – обычно тут особых проблем не бывает.

Интересно, что некоторые разработчики, помучившись с JPA, уходят в NoSQL – там таких проблем принципиально нет из-за отсутствия JPA. При этом они находят другие, но это отдельная история.

Альтернативы

Среди альтернатив выделяются MyBatis и JetBrains Exposed.

MyBatis выглядит как промежуточный шаг от JPA к SQL. Вроде бы уже не первое, но SQL-типизации нет.

Exposed, понятное дело, сконцентрировано на языке Котлин. Есть DSL для работы в SQL. 2 проблемы: нет понимания, что это именно Postgres (соответственно не полная типизация) и нет генерации кода по схеме в базе. Т.к. проекту уже не первый год, то, скорее всего, и не предвидится. Так же, как я понял, нет поддержки реактивности.

SQL

Так же возникло обратное движение – давайте максимально использовать SQL. Но не в строках, а типизировано – для конкретной версии БД и даже конкретной схемы (в идеале код генерируется по схеме в базе). Миграции тоже будем писать на SQL. Таким образом, мы получаем полноценный доступ к конкретной версии базы данных (не зря же версия Postgres уже 15.2 и разработки продолжаются).

Это представлено 2-мя библиотеками: Querydsl и jOOQ. Querydsl уже несколько лет не обновляется, а jOOQ – полуоткрытая библиотека.

Итог

Идеала нет, пока что использую jOOQ и вполне доволен. Еще думаю для простых случаев использовать Spring Data репозитории.