От переводчика: это статья моего коллеги @aleksey-stukalov, которую мы опубликовали в блоге JPA Buddy пару месяцев назад. С тех пор мы выпустили JPA Buddy 2.0, но все сказанное в этой статье актуальности не потеряло.
Ну что ж, Hello World... После почти года разработки наконец-то вышла первая версия JPA Buddy! Это инструмент, который должен стать вашим верным помощником по написанию кода для проектов с JPA и всем, что с этим связано: Hibernate, Spring Data, Liquibase и другим ПО из типичного стека разработки.
Чем он вам поможет? Если кратко, JPA Buddy упростит работу с JPA и тем самым сэкономит ваше время. В этой статье мы взглянем на основные фичи JPA Buddy, немного обсудим его историю и поговорим о его преимуществах. Надеюсь, он займет достойное место среди любимых инструментов Java-разработчиков, которые пользуются JPA, Spring, Liquibase и, конечно же, самой продвинутой Java IDE — IntelliJ IDEA.
Откуда растут ноги
Мы — создатели CUBA Platform (кстати, не так давно мы переименовали ее в Jmix :)) — среды быстрой разработки приложений на Java. Платформа CUBA — уникальный продукт. Он состоит из двух частей: фреймворка и инструмента разработки CUBA Studio. Одной из самых полюбившихся частей CUBA Studio стал «Entity Designer». В сообществе CUBA более 20 000 разработчиков, и почти все они отмечают, насколько легко и быстро он дает создавать модель данных. Даже для тех, кто никогда не слышал о JPA, такие вещи как создание JPA-сущностей, ограничений модели данных и DDL-скриптов становятся легкой задачей.
В 2016 году CUBA стала open-source проектом. С того момента мы приняли участие в десятках конференций по всему миру, собрали много отзывов и лучше поняли, что именно нужно разработчикам. Они нас часто спрашивали: «Можно ли использовать ваш конструктор сущностей без CUBA Platform?». Рады сообщить, что с появлением JPA Buddy мы теперь можем смело ответить «да!».
JPA Buddy не требует дополнительных зависимостей — это просто инструмент. Вы можете пользоваться им не только на новых, но и на уже существующих проектах, которые используют JPA. Это плагин для IntelliJ IDEA, который помогает вам писать связанный с JPA код, находить и исправлять потенциальные ошибки, проводить рефакторинг и выполнять другие трудоемкие, но достаточно шаблонные операции.
Область применения
Перед тем, как написать первую строчку исходного кода JPA Buddy, мы провели опрос и собрали различные сценарии использования JPA и сопутствующих технологий. Результат оказался достаточно предсказуемым: среднестатистическое приложение в настоящее время — это приложение на Spring Boot с Hibernate в качестве реализации ORM, Spring Data JPA в качестве механизма управления данными и Flyway или Liquibase для системы миграции базы данных. Ах да, чуть не забыли про Lombok... В общем, на этом стеке мы и сконцентрировались в первом релизе.
Говоря о предназначении JPA Buddy, мы поставили перед собой следующие цели:
Сократить написание шаблонного кода вручную: инструмент должен генерировать код быстрее ручного ввода
Не заставлять тратить время на чтение документации: инструмент должен предоставлять интуитивно понятные визуальные конструкторы
Оставить свободу выбора: инструмент должен не диктовать какой–либо конкретный стиль написания кода, а поддерживать его различные варианты
Выявлять потенциальные проблемы и предлагать решения для наиболее распространенных: инструмент должен предупреждать разработчика о проблемах на этапе написания кода, а не в рантайме
Обеспечить обзор проекта с точки зрения данных и удобную навигацию между связанными сущностями
В первом релизе мы смогли реализовать достаточно значительный объем функциональности, охватывающей большинство аспектов разработки модели данных. Хорошая новость для тех, кто использует Liquibase: инструменты для работы с ним уже реализованы и доступны. Не очень хорошая новость для пользователей Flyway: он входит в список наиболее приоритетных фич :)
В долгосрочной перспективе мы собираемся реализовать следующие функции:
Аннотации Hibernate: @Where, @NaturalId, @Formula, поисковые аннотации и т. п.
Визуальный конструктор запросов
Аудит с использованием Envers и Spring Data JPA
Генерация модели по существующей схеме базы данных
Поддержка Kotlin
В дальнейшем мы учтем и другие функции: поддержка Quarkus и Micronaut, REST API и генерация пользовательского интерфейса для CRUD-операций.
Как видите, впереди еще долгий путь, и мы были бы очень признательны за вашу помощь в расстановке приоритетов разработки — не стесняйтесь высказывать свою точку зрения через нашу форму, Twitter или Discord.
Общий обзор
Давайте посмотрим, как выглядит JPA Buddy. После его установки у вас появятся 3 новые панели инструментов: JPA Structure, JPA Palette и JPA Inspector.
JPA Structure
Панель JPA Structure расположена в левом нижнем углу. Она позволяет посмотреть на проект с точки зрения модели данных. С ее помощью можно:
Перемещаться по модели данных. Структура сущностей представлена в иерархическом виде. По ней легко перейти к объектам, ссылающимся на текущий объект, и к тем, на которые ссылается текущий объект. Это особенно полезно для тех, кто только начинает погружаться в существующий проект с большим графом сущностей, или для код-ревьюеров, которые видят часть модели впервые и им нужно в ней быстро разобраться.
Создавать объекты, связанные с данными: сущности, JPA-конвертеры/Hibernate-типы, Spring Data репозитории и Liquibase-скрипты.
Увидеть, для каких сущностей созданы какие репозитории.
Просматривать скрипты Liquibase и их внутреннюю структуру.
Настраивать параметры плагина, такие как соединение с БД, Persistence Units и некоторые другие, которые плагин не обнаружил автоматически.
JPA Palette и JPA Inspector
Панель JPA Palette находится справа вверху, и ее содержимое зависит от контекста. Она доступна только тогда, когда Buddy готов предложить что–то для быстрой генерации кода. Сейчас панель появляется при редактировании следующих объектов: JPA Entity, Spring Data репозиториев и Liquibase-скриптов. Для генерации какого-либо элемента просто выберите нужный вариант в списке и кликните по нему дважды.
JPA Inspector размещается справа внизу, под JPA Palette, и открывается вместе с ним. С помощью JPA Palette можно генерировать новый код, а с помощью JPA Inspector редактировать уже существующий. В нем видно, как можно сконфигурировать выбранную часть кода, будь то поле сущности или выражение из Liquibase-скрипта.
Все это будет полезно как для новичков, так и для опытных разработчиков. Первые могут посмотреть на полный список вариантов, выбрать подходящий и сгенерировать корректный код с помощью понятных визуальных конструкторов. Сеньоры, в свою очередь, часто забывают мелочи, которые не используются в повседневной жизни, и Buddy сэкономит несколько секунд драгоценного времени на поиск в документации правильной аннотации или синтаксиса.
Интеграция с Liquibase
Хорошие новости для тех, кто использует Liquibase для управления версиями схемы базы данных: JPA Buddy тесно с ним интегрирован, он позволяет удобно редактировать и создавать Liquibase-скрипты, а также гибко управлять типами атрибутов. Давайте посмотрим, как именно JPA Buddy поможет вам работать с Liquibase.
Во-первых, в JPA Buddy есть визуальный конструктор для редактирования Liquibase-скриптов. Он показывает различные доступные команды плагина в JPA Palette, а панель инструментов JPA Inspector дает увидеть настройки, которые можно применить к выбранному выражению.
Во-вторых, JPA Buddy дает определить свои собственные маппинги для сопоставления Java-типов (Конвертеров/Hibernate–типов) и типов, которые должны использоваться для каждой конкретной СУБД. Приведем несколько примеров, когда эта функция будет полезна:
Допустим, у вас в сущности есть поле типа byte[]. Что генератор схемы Hibernate, что Liquibase сопоставят ваш массив с довольно экзотическим типом “OID”. Думаю, многие разработчики предпочли бы использовать bytea вместо предлагаемого по умолчанию типа. Это можно легко сделать, создав маппинг с Java-типа byte[] на БД-тип bytea в настройках проекта в JPA Buddy.
Использование JPA-конвертера или кастомного Hibernate-типа вызывает непредсказуемое поведение или даже ошибки в стандартных генераторе схемы Hibernate и генераторе скриптов Liquibase. С помощью JPA Buddy можно явно указать нужный тип, чтобы решить эту проблему.
Поля типа String по-умолчанию хранятся как varchar, то есть не поддерживают Юникод. С помощью JPA Buddy легко изменить этот тип на nvarchar, с которым этой проблемы нет.
Все эти случаи обычно решаются с помощью атрибута columnDefinition, однако это решение не будет работать для проектов, где одновременно используется несколько СУБД. JPA Buddy позволяет указать, какой именно маппинг использовать для конкретной СУБД.
Наконец, функция, экономящая наибольшее количество времени — наш генератор Liquibase-скриптов. Исходя из нашего опыта (который совпадает с опытом разработчиков принявших участие в ранее упомянутом опросе), есть два основных способа создания Liquibase-скриптов:
Написание вручную
Создание скриптов путем сравнения двух баз данных: исходной (представляющей фактическое состояние модели) и целевой (с предыдущим состоянием модели)
Для тех, кто предпочитает первый вариант, JPA Buddy включает уже упомянутый ранее конструктор Liquibase-скриптов.
Однако, второй вариант наиболее распространен. Итак, сравниваем две базы данных. Целевую базу данных относительно легко получить, например, можно просто создать дамп базы данных продакшена. Сложности возникают с получением исходной базы данных.
Начнем с небольшой проблемы: может случиться так, что база данных, используемая для разработки на ноутбуке разработчика, не того же типа, что и база данных на продакшене. Это можно исправить, например, запустив MS SQL в Docker на Mac.
Более серьезная проблема состоит в том, что трудно найти «чистую» исходную базу данных, поскольку она обычно формируется в процессе разработки генератором схемы Hibernate. Часто это приводит к большому количеству «мусорных» таблиц и атрибутов, которые в конечном итоге появляются в базе данных продакшена. Чтобы избежать подобного рода «мусора», приходится тратить еще час или два на просмотр схемы базы данных перед запуском генерации Liquibase-скриптов.
В JPA Buddy есть замечательная функция генерации Liquibase-скриптов напрямую, путем сравнения ваших объектов JPA с целевой базой данных (или snapshot’ом целевой базы данных). Вы можете использовать H2 в целях разработки и по-прежнему генерировать правильные журналы изменений для Oracle, MS SQL или того, что вы используете в продакшене. Подобный подход гарантирует, что если у вас есть «мусор» в журналах изменений, это именно тот «мусор», который есть у вас в исходном коде. Все, что вам нужно, — это содержать модель данных в чистоте, и тогда миграция не приведет к нежелательным артефактам в базе данных продакшена.
Еще одна особенность генератора журнала изменений — это возможность фильтровать полученные выражения по 3 категориям:
содержащие только безопасные операторы, которые не могут дать сбой при обновлении или полностью уронить ваше приложение, например, добавление нового столбца
содержащие инструкции, которые могут завершиться ошибкой при обновлении, но не привести к потере данных, например, применение ограничения уникальности
содержащие операторы, которые вызовут потерю данных, например, удаление таблицы или столбца
Вы сами решаете, как разделить такие утверждения: поместить их в отдельные скрипты Liquibase или просто выбрать им нужную метку или контекст в редакторе.
Заключение
В этой статье мы посмотрели на первый релиз JPA Buddy. Очевидно, что как и любой новый продукт, JPA Buddy не может полностью избежать проблем и багов, особенно в своем первом релизе. Сейчас мы концентрируемся на устранении замечаний от пользователей, улучшении существующей функциональности, определении наиболее приоритетных функций, которые мы могли упустить из виду, и их реализации.
Говоря прямо, мы хотели бы вдохновить вас стать первыми пользователями JPA Buddy и сформировать сообщество энтузиастов. Установите JPA Buddy, попользуйтесь им и поделитесь своими отзывами с нашей командой разработчиков: это очень поможет нам выбрать правильное направление развития продукта. Также подпишитесь на наш Twitter: там мы показываем, какие еще фичи есть у JPA Buddy и как ими пользоваться. Думаю, вы найдете что-то полезное именно для вас.