В мире разработки программного обеспечения очень любят аббревиатуры. И работа с базами данных в Java — не исключение. Наличие множества вариантов работы с БД может запутать: что же я использую на самом деле? Все используют JPA? Мне тоже стоит его использовать? Но я еще слышал о Spring Data JDBC. А как насчет Spring Data JPA? В этой статье мы поговорим о JDBC и JPA: истории появления и некоторых особенностях. JDBC — это Java Database Connectivity API. Это старый стандарт, уходящий корнями в 1997 год во времена Java 1.1. И этот API сослужил нам добрую службу. Абсолютно все библиотеки, взаимодействующие с базами данных, используют JDBC. В этом есть как преимущества, так и недостатки. По сути, JDBC — это Java-реализация стандартного подхода к работе с базами данных, реализованного во всех подобных технологиях: Открыть соединение. Открыть курсор. Отправить запрос. Обработать набор данных. Закрыть результирующий набор / курсор. Закрыть соединение. И вы наверняка сталкивались с ситуацией, когда, выполняя десятки запросов, забывали закрыть соединение. А шесть недель спустя получали ужасный стек-трейс из-за того, что каким-то образом в базе данных закончились соединения или курсоры. Вы быстро понимали в чем дело, чинили и отправляли в релиз. Но через восемь недель — та же самая ошибка.  Разработчики Spring обратили на это внимание, и в Spring появился паттерн JdbcTemplate. Template позволил вам сосредоточиться непосредственно на запросах и их результатах. Теперь за управление ресурсами отвечал фреймворк. Вам больше никогда не позвонят в 3 часа ночи, потому что ваша база данных/приложение упали. Ладно, возможно, вы все еще получаете звонки среди ночи. Но не потому, что забыли закрыть соединение! Я думаю, что после написания десятков запросов к одному и тому же объекту Item, вы задумывались: "Почему Java, зная тип объекта, не может сгенерировать запрос за меня?" И здесь появляется Hibernate — предвестник JPA. В течение многих лет мы мучились с маппингом строк таблиц БД на Java-объекты, а также с различиями между разными СУБД. При переходе с Oracle на Postgres мне придется переписывать все запросы? Иногда, да. Потому что в каждой СУБД есть свои особенности и реализации стандарта ANSI SQL отличаются от СУБД к СУБД.  Hibernate принес унифицированный подход для персистентности Java-объектов — надо только настроить маппинг таблиц БД на Java-классы. Изначально для конфигурации маппинга использовался XML, но с появлением Java 5 перешли на аннотации! И все понеслось с космической скоростью! Унификация общения с разными СУБД, когда один и тот же запрос можно выполнить на любой СУБД — это действительно круто. Но осталась одна проблема, которую мы не осознавали до конца. Хорошо, хорошо, были те, кто понимали это, но большинство — нет. Вы никогда не сможете по-настоящему избежать настройки маппинга реляционных таблиц. Если вы используете Hibernate, это еще не значит, что можно перестать думать в терминах реляционных баз данных. Да, для простейших запросов проблем нет. Это весьма простой запрос. Он может быть универсальным. Как раз в таких ситуациях Hibernate приводит в полный восторг.  В итоге Hibernate стандартизовали из-за его популярности. JPA — это Java Persistence API (аббревиатура внутри аббревиатуры). Hibernate стал основой для него. Большинство разработчиков, использующих JPA, на самом деле используют Hibernate. JPA был настолько продуманным, что окрылял вас.  Но мы неизбежно обнаружим, что в JPA есть страшная тайна, о которой мы где-то прочитали или догадались сами: вы никогда, никогда не уйдете от концепции реляционных таблиц. По мере написания более сложных, более запутанных и более бизнес-ориентированных запросов вы обнаружите, что Java-объекты не всегда соответствуют этой парадигме. То есть вы просто променяли свои знания SQL на знания JPA. На самом деле, он довольно мощный. Но иногда этой силе требуется небольшая помощь, поэтому и был создан Spring Data JPA. Spring Data JPA помогает вам с простыми запросами и избавляет от необходимости работать с EntityManager из JPA. Хотя рано или поздно вам все-равно придется писать JPQL-запросы вручную. Но если вы думаете, что написав, сложный и тонко настроенный JPQL-запрос вы сможете каким-то образом настроить генерацию оптимального SQL-запроса, вас ждет большое разочарование. В былые времена администраторы баз данных помогали найти медленные запросы. А проанализировав план выполнения, вы могли понять, как запрос выполняется и где тратит время. И можно было заняться оптимизацией БД и запроса: создать индексы; актуализировать статистику; переписать JOIN; избавиться от функций вроде UPPER (или LOWER), чтобы избежать полных сканирований таблиц; убрать десятки JOIN одной и той же таблицы (да, однажды я видел и такое). А также использовать десяток других приемов. После оптимизации ваш двадцатиминутный запрос мог выполняться за секунду. Это было обычным делом при обслуживании баз данных/приложений. Но с SQL-запросами, генерируемыми через JPA, вы не сможете этого сделать. Некоторые стали называть это девятым кругом JPA. Может для вас это допустимо, но для многих — весьма неприятно. Поэтому многих воодушевил Spring Data JDBC, появившийся в 2017 году. На конференции SpringOne в 2018 году зал был набит людьми, жаждущими услышать новости об этом. Spring Data JBDC делает много работы за вас, но не все, что делает старый добрый Hibernate. Предполагается, что вручную вы напишете более оптимальный запрос как во времена чистого JDBC. У вас появляется возможность видеть SQL-запросы и настраивать их в соответствии с вашими потребностями. Теперь, имея представление об этих технологиях (JdbcTemplate, Spring Data JPA, Spring Data JDBC) вы сможете сделать осознанный выбор в отношении того, что лучше подойдет вам в вашей ситуации. Когда говорим про память в Java, то чаще всего вспоминают Heap и Garbage Collector. Но у нас есть больше не менее интересного в памяти, о чем мы и поговорим на открытом занятии «Не хипом единым живёт Java». Приглашаем зарегистрироваться всех желающих.  Редактор