Добавить идею поддержки фреймворка без гибернации

Обновлено: 21.11.2024

Вы строите следующий большой проект? Планируете стать следующим Facebook или Google? Готовы ли вы принять фундаментальные решения, которые останутся с вами на протяжении всего проекта? Есть большая вероятность, что вы выберете надежный язык, такой как Java. Если это так, вы хотите выбрать наилучшую объектно-ориентированную абстракцию своей гибкой модели данных, потому что не хотите иметь дело с простым SQL. Вы хотите поддерживать все виды данных и, в идеале, поддерживать все виды баз данных. Если это так, для вас есть только один правильный выбор: спящий режим. Внештатный инженер-программист Гжегож Гайош исследует возможные сценарии, в которых что-то может пойти не так при использовании Hibernate.

Гржегож — архитектор программного обеспечения с международным опытом консультирования и программирования, а также соучредитель компании Open Tangerine Software.

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

Очевидный ответ — просто использовать Hibernate, верно? 90 % Java-разработчиков согласятся с вами, но делает ли это решение правильным?

Давайте посмотрим, что может пойти не так, если вы слепо используете Hibernate только потому, что это общепринятый стандарт.

Возьмем Монику, разработчика Java. Монику недавно повысили до должности архитектора, и теперь она отвечает за разработку стека технологий для нового продукта в своей компании. Она знает, что в мире Java есть только один хороший инструмент для взаимодействия с базой данных: Hibernate. Hibernate — это хорошо известный и поддерживаемый стандарт JPA. Тем не менее, всегда полезно проверить несколько вещей перед началом проекта. К счастью, ее коллега Бен знает нужного парня.

Hibernate звучит как серебряная пуля

Бен. Привет, Моника. Я хочу представить Джона. Он эксперт по Hibernate и поможет вам.

Моника. Привет, Джон, рад, что ты нашел для меня время. Итак, вы знаете, мы строим нашу следующую большую вещь. Мы планируем стать следующим Facebook или Google. Напряженные дни. Это будет грандиозно. Абсолютно фантастично! Все так взволнованы! Меня повысили до роли архитектора, так что теперь мне нужно выбрать стек, который мы будем использовать. Единственная недостающая часть — это настойчивость…

Джон - Спящий режим!

Моника - Да! Точно! Как раз то, что я думал! Это похоже на идеальное совпадение и реальную сделку для нас. Настоящее корпоративное решение для реальной корпоративной проблемы, проверенное рынком и имеющее долгую историю. Слышал много положительных отзывов о нем. Однако у меня есть проблема с одним из наших товарищей по команде; он категорически против. Он много знает о базах данных и боится добавить еще один слой между нашим приложением и базой данных. Он очень умен, и мне нужны действительно веские аргументы, чтобы убедить его, что это правильное решение. Вы можете помочь мне с этим?

Джон – Конечно! буду рад. Hibernate — действительно выдающийся инструмент. Он широко используется в крупных, настоящих корпоративных решениях, таких как банки. Вы не ошибетесь. Подумайте о постоянстве: выберите Hibernate. Если вы пишете на Java, это абсолютно правильный выбор, плюс у вас есть порты для других языков. Посмотрите, сколько описаний вакансий требуют этого!

Моника - Абсолютно согласна! У меня такие же чувства по этому поводу. В предыдущем проекте мы использовали в основном SQL через старый добрый JDBC. Нелепый! Я знаю! Но вот в чем дело: у нас в команде есть очень умные специалисты по SQL, и когда они увидели SQL, сгенерированный Hibernate, они занервничали. Это казалось уродливым и нечитаемым; будет ли это проблемой в будущем?

Джон – Смотри. Ребята из DBA придерживаются другой точки зрения. Они боятся спящего режима, потому что он заменяет их роль в проекте. Кроме того, базы данных имеют встроенные оптимизаторы запросов, поэтому вам не нужно беспокоиться о том, как эти запросы будут выглядеть на самом деле. База данных оптимизирует его для вас. Все дело в быстрой разработке, чего SQL не может.

Моника - Правда?! Больше не имеете дело с SQL? Удивительно! В прошлый раз администратор баз данных потратил недели, пытаясь оптимизировать некоторые запросы. Недели! О, мне так неловко вам это говорить, но знаете ли вы, что мы использовали… хранимые процедуры (смеется). О, это был такой беспорядок. Можете ли вы поверить, что проект все еще использует его? Мне так жаль людей там. Им все еще приходится писать этот утомительный код снова и снова. Интересно, это по-прежнему проект Java или SQL?

Джон. В этом и заключается разница между объектно-ориентированным подходом и реляционным. Это так называемое объектно-ориентированное несоответствие импеданса. Hibernate может закрыть этот пробел.Разработчики могут сосредоточиться на построении бизнес-логики. Push-функции делают заинтересованные стороны и все руководство счастливыми. Делайте то, что важнее всего: Бизнес! Исчезнет много стандартного кода, и у вас появится волшебная, невидимая, но надежная связь между логикой и данными.

Моника - Взаимное сотрудничество. Полная синергия. Как будто база данных была частью языка с самого начала. Я так счастлив, что стал лидером этого технологического прыжка веры. Это похоже на скорость деформации в программном путешествии.

Джон – Ага! У тебя получилось!

Моника – О боже, я так взволнована! Спасибо, Джон! Я готов!

Болезни роста из-за негибких решений

Моника. Привет, Джон, помнишь проект, о котором мы говорили в прошлом году?

Джон – Конечно. Как дела?

Моника - Мы скоро приступим к производству. Все хорошо, но возникли некоторые вопросы.

Джон – Конечно, ударь меня.

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

Джон. Ну, во-первых, Hibernate не предназначен для использования в качестве инструмента переноса рабочей среды. Используйте что-то вроде FlywayDB или Liquibase. Это довольно просто. Вы записываете сценарии переноса, а затем обновляете модель объекта вместе с сопоставлениями Hibernate, чтобы она синхронизировалась с фактической структурой базы данных.

Моника – Хм, понятно. В предыдущем проекте мы использовали простую миграцию SQL.

Джон – Тоже хорошо. Пока вы синхронизируете модель объекта и схему, делайте это так, как вам нравится.

Моника, понятно. Есть еще одна вещь. Мы всегда боремся с проблемами ленивой/нетерпеливой выборки. В какой-то момент мы решили сделать все на скорую руку, но это кажется неоптимальным, к тому же иногда не получается получить доступ к некоторым полям из-за отсутствия сессии или чего-то в этом роде. Это нормально?

Джон. Вам нужно узнать больше о Hibernate. Отображение из базы данных не является простым. В принципе, есть несколько способов сделать это. Вам просто нужно выбрать способ, который работает для вас. Ленивая загрузка дает вам возможность загружать эти объекты по запросу, но вам нужно работать в рамках активного сеанса.

Моника. Мы все еще пытаемся решить, какой механизм базы данных использовать для окончательного развертывания. Я думал, что Hibernate можно переносить, но у нас есть несколько нативных запросов, использующих волшебство MS SQL, и мы действительно хотели бы работать с MySQL в рабочей среде.

Джон — Hibernate дает вам гибкость, если вы используете отдельные критерии или HQL; любые нативные запросы просто привяжут ваше решение к базе данных.

Моника. Похоже, нам придется придерживаться MS SQL. Последний вопрос: мой товарищ по команде сказал, что в HQL нет ключевого слова «лимит». Я думал, что он шутит, но тоже не нашел. Извините за глупый вопрос…

Джон. Действительно, в HQL нет ключевого слова «предел». Вы можете управлять этим с помощью объекта запроса, поскольку он зависит от поставщика базы данных.

Моника. Странно, что все остальные элементы в HQL. Неважно. Спасибо за ваше время!

Теперь мы снова вместе разрабатываем решения на SQL

Моника - Джон, поначалу мы не собирались заниматься SQL, а теперь, похоже, придется. Наши потребности растут, и кажется, что нет другого выхода. Это кажется неправильным, но мы снова начали ежедневно использовать SQL.

Джон – Что ж, это не так. Вам не нужно было фокусироваться на базе данных в самом начале. Однако по мере роста проекта полезно использовать SQL и работать над оптимизацией производительности.

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

Джон. Всегда нужно учиться. Вам не нужно много писать, но вам нужно знать, как это работает.

Моника. Работа с большими наборами данных также раздражает. Недавно мы сделали массивный импорт в базу данных, и он был мучительно медленным. Затем мы обнаружили, что нам нужно очистить сеанс, чтобы сделать его быстрее. Несмотря на это, он все еще значительно медленнее, поэтому мы решили переписать его в виде простых операторов SQL. Что забавно, так это то, что написание простого SQL оказалось самым быстрым способом сделать это, поэтому мы решили использовать его как последний вариант.

Джон. Импорт не является объектно-ориентированным процессом. Hibernate ориентирован на объектно-ориентированный дизайн. Помните, что вы всегда можете использовать собственные запросы.

Моника. Не могли бы вы помочь мне понять, как работает кеш Hibernate? Я просто не понимаю.Есть несколько кешей первого/второго уровня. О чем это все?

Джон – Конечно. Это так называемый кэш постоянных данных на уровне транзакций. Кэш уровня кластера или JVM можно настроить для каждого класса и коллекции за коллекцией. Вы даже можете подключить кластерный кеш. Но помните, что кеши не знают об изменениях, внесенных в постоянное хранилище другим приложением. Однако их можно настроить на регулярное удаление просроченных кэшированных данных.

Моника. Извините, кажется, у меня плохой день. Не могли бы вы объяснить это немного подробнее?

Джон – Конечно. Всякий раз, когда вы передаете объект в save, update, saveOrUpdate или извлекаете его с помощью load, get, list, iterate или scroll, этот объект добавляется во внутренний кэш сеанса. Вы также можете удалить объект и его коллекции из кеша первого уровня.

Моника - Э-э…

Джон. Кроме того, вы можете управлять режимами кэширования. Вы можете использовать обычный режим для чтения и записи элементов в кэш второго уровня. Используйте режим получения для чтения со второго уровня, но вы не можете писать обратно. Используйте put, то же самое, что и get, но вы не можете читать со второго уровня. Вы также можете использовать режим обновления, который будет записывать на второй уровень, но не читать из него, и обходить свойство использования минимальных путов, принудительно обновляя кэш второго уровня для всех элементов, считанных из базы данных.

Моника, понятно. Ok. Позвольте мне подумать об этом. О, уже поздно, мне нужно идти. Спасибо за ваше время!

Джон – Добро пожаловать!

Отказ от гибернации

Моника. Джон, я думал, что мы вступаем в новую эру разработки программного обеспечения. Я думал, мы совершаем прыжок на световой год. Но по прошествии четырех лет кажется, что мы все еще решаем все те же проблемы, только под другим углом. Мне пришлось изучить архитектуру Hibernate, конфигурацию, ведение журнала, стратегии именования, туплайзеры, преобразователи имен сущностей, расширенные генераторы идентификаторов, оптимизацию генераторов идентификаторов, объединение-подклассы, разметку XDoclet, двунаправленные ассоциации с индексированными коллекциями, тернарные ассоциации. , idbag, смешивание неявного полиморфизма с другими сопоставлениями наследования, репликация объекта между двумя разными хранилищами данных, отсоединенные объекты и автоматическое управление версиями, режимы освобождения соединения, интерфейс сеанса без сохранения состояния, таксономия сохраняемости коллекции, уровни кэша, ленивая или активная выборка и многое-многое другое. Даже со всем, что я знаю, кажется, что мы сильно потерпели неудачу. Это фиаско программного обеспечения! Полный провал! Катастрофа! Армагеддон!

Джон – Подожди! Что случилось?

Моника – Мы зашли в тупик. Производительность нашего приложения смехотворно низкая! Чтобы получить отчет, мы должны ждать два дня! Два дня, чтобы фактически сгенерировать информационную панель для клиента. Это означает, что каждый день нам приходится наращивать хвост вычислений, а наш дашборд все больше и больше устаревает. Наш специалист по администрированию баз данных два месяца работал над оптимизацией некоторых запросов, а структура нашей базы данных в полном беспорядке. Есть разработчики, поддерживающие его, но проблема в том, что администратор базы данных думает на языке SQL, и разработчики тратят дни, пытаясь перевести это в отдельные критерии или формат HQL. Мы пытаемся максимально использовать нативный SQL, поскольку на данный момент производительность имеет решающее значение. В любом случае, мы мало что можем сделать, так как схема базы данных кажется неправильной. Это кажется правильным с точки зрения объектно-ориентированного подхода, но кажется нелепым с реляционной точки зрения. Я спрашиваю себя: как это произошло? Разработчики говорят нам, что изменение структуры сущностей потребует огромных усилий, поэтому мы не можем себе этого позволить. Помню, в предыдущем проекте был бардак, но мы никогда не оказывались в такой критической точке. Мы смогли написать совершенно другое приложение для работы с данными. Теперь изменять эти сгенерированные таблицы рискованно, поскольку очень сложно убедиться, что модель объекта всегда будет вести себя правильно. И это еще не самое страшное! Чтобы повысить производительность, мы должны решить не только проблемы с базой данных, но и проблемы со всем слоем между нашей базой данных и приложением. Это потрясающе! У нас есть эти новые ребята, вы знаете, консультанты. Они пытаются извлечь данные, поместить их в какое-то другое хранилище, а затем выполнять вычисления извне. Все это занимает слишком много времени!

Джон, я не знаю, что сказать.

Моника – Вы видите Джона; Я не хочу винить тебя. Я выбрал Hibernate, чтобы решить все эти проблемы, но теперь я узнал, что это не панацея. Ущерб нанесен, и он необратим. На самом деле, я хотел бы спросить вас кое о чем: последние четыре года своей карьеры я занимался вещами Hibernate. Кажется, у меня нет будущего в моей нынешней компании. Вы можете мне помочь?

Какой урок мы извлекли?

Джон – Привет, Питер, позвольте представить Монику.

Питер – Эй, Моника! Мы строим нашу новую большую вещь, которую вы знаете. Он будет огромным! Мы хотим быть как Uber!Знаете ли вы, может быть, как настойчивость…

Моника – не спящий режим!

Подведение итогов

Моника — эксперт по Hibernate. Однако спящий режим в данном случае был неправильным решением. В тот момент, когда она обнаружила, что ее решение превратилось в большую проблему, чем оригинал, это стало самой большой угрозой для всего проекта.

Данные — это основная цель приложения, и, нравится вам это или нет, они влияют на всю архитектуру. Как мы узнали из этой истории, не используйте Hibernate только потому, что ваше Java-приложение использует базу данных или из-за социального доказательства. Выберите решение, обеспечивающее гибкость. Существует множество вариантов надежных оболочек JDBC, таких как JdbcTemplate или Fluent JDBC Wrapper. Кроме того, есть другие мощные решения, такие как jOOQ.

Эта информация действительна для проектов, созданных с помощью собственного компоновщика IntelliJ IDEA. Если вы используете инструмент сборки, такой как Maven или Gradle, вносите все изменения с помощью файла сборки.

Для разработки приложений для конкретных платформ в IntelliJ IDEA предусмотрены аспекты. Фасеты содержат библиотеки, зависимости и технологии, а также предоставляют дополнительные элементы пользовательского интерфейса для настройки параметров конкретной платформы.

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

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

Если фасет не определяется автоматически, вы можете добавить его вручную. В модуль можно добавить более одного аспекта.

Некоторые платформы доступны только в IntelliJ IDEA Ultimate. Обратитесь к таблице сравнения, чтобы убедиться, что ваша версия IntelliJ IDEA поддерживает необходимые платформы.

Добавить фасет в модуль вручную

В окне инструмента "Проект" Alt+1 щелкните правой кнопкой мыши модуль, к которому вы хотите добавить фасет, и выберите "Добавить поддержку платформы" .

Выберите нужный фреймворк из списка.

В зависимости от вашего выбора вам может быть предложено настроить дополнительные параметры (например, настроить библиотеку).

Примените изменения и закройте диалоговое окно.

Отключить автоматическое определение фреймворка

По умолчанию автоматическое определение включено для всех поддерживаемых платформ. Вы можете полностью отключить автоматическое определение фреймворка или исключить отдельные фреймворки из автоматического определения.

В главном меню выберите Файл | Структура проекта ( Ctrl+Alt+Shift+S ) и выберите Фасеты .

Выберите «Обнаружение» и нажмите Alt+Insert .

В списке Framework to Exclude выберите нужный вариант.

Вы можете отключить автоопределение определенного фреймворка только в одном каталоге или во всем проекте. Список также позволяет отключить автоматическое определение всех фреймворков в определенном каталоге.

Если вы хотите отключить автоматическое определение всех фреймворков во всем проекте, снимите флажок Включить определение фреймворка.

Чтобы снова включить автоматическое обнаружение везде, установите флажок Включить обнаружение платформы и удалите все записи из списка Исключить из обнаружения.

Читайте также: