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