Object relational mapping java

Hibernate — ORM, JPA, JPQL

ORM (Object-Relational Mapping, объектно-реляционное отображение) — технология программирования, которая связывает базы данных с концепциями объектно-ориентированных языков программирования. В объектно-ориентированном программировании объекты приложения представляют объекты реального мира. ORM предназначена для преобразования объектов в форму для их сохранения в файлах или базах данных, а также их дальнейшего извлечения в программе с сохранением свойств объектов и отношений между ними. Такие объекты называют «хранимыми» (persistent). ORM освобождает программиста от работы с SQL-скриптами и позволяет сосредоточиться на ООП.

В программе основой ORM является конфигурационный файл, в котором описывается порядок хранения объекта в БД. Если с обычными полями все прозрачно : строковое поле записывается в колонку с типом varchar, а целочисленное — в int, то со связями между объектами все гораздо интересней. Например, в программе используются классы «Город» и «Улица». Для обоих классов созданы конфигурационные файлы, в которых описаны их поля и связи с таблицами БД. Но кроме этого «Улица» имеет ссылку на «Город». В таком случае таблицы в БД будут связаны по внешнему ключу, что также должно быть описано в одном из конфигурационных файлов.

JPA — Java Persistence API, javax.persistence

Для сохранения Java-объектов в базе данных и чтения из БД следует использовать JPA. JPA (Java Persistence API) — программный интерфейс API, входящий с версии Java 5 в состав платформ Java SE и Java EE. Существует несколько реализаций интерфейса JPA, среди которых наиболее популярным является Hibernate.

Читайте также:  Php artisan could not open input file

Непосредственно JPA представлен в пакете javax.persistence и включает платформо-независимый объектно-ориентированный язык запросов JPQL.

JPA оперирует таким понятием, как сущность Entity, которая является POJO-классом и связана с БД с помощью аннотации @Entity или через файл конфигурации XML. К такому классу предъявляются следующие требования :

  • наличие пустого public или protected конструктора;
  • не должен быть вложенным, являться интерфейсом или enum;
  • не должен быть final и не должен содержать final-свойств;
  • должен включать хотя бы одно @Id-поле.

При этом сущность может иметь непустые конструкторы, наследоваться или быть наследованной, содержать методы, не связанные со свойствами (методы get/set), и реализовывать интерфейсы. Entities могут быть связаны друг с другом (один-к-одному, один-ко-многим, многие-к-одному и многие-ко-многим).

Примеры сущностей Entity

В самом простом виде (без методов определения и получения значения свойств) JPA сущности можно представить следующим образом :

@Entity public class Author < @Id private Integer id; private String firstName; private String lastName; @ManyToMany private Listbooks; > @Entity public class Book < @Id private Integer id; private String title; private String isbn; @ManyToOne private Publisher publisher; @ManyToMany private Listauthors; > @Entity public class Publisher < @Id private Integer id; private String name; private String address; @OneToMany(mappedBy = "publisher") private Listbooks; >

При описании сущностей были использованы аннотации. Пример использования аннотаций при описании сущности представлено здесь.

JPQL — Java Persistence Query Language

Java Persistence Query Language (JPQL) — платформо-независимый объектно-ориентированный язык запросов являющийся частью спецификации JPA.

JPQL используется для написания запросов к сущностям, хранящимся в реляционной базе данных. JPQL во многом похож на SQL, но в отличие от последнего, оперирует запросами, составленными по отношению к сущностям JPA, в отличие от прямых запросов к таблицам базы данных. В дополнение к получению объектов (запросы SELECT), JPQL поддерживает запросы, основанные на операторах UPDATE и DELETE. JPA реализует концепцию ORM.

JPQL основан на Hibernate Query Language (HQL), более раннем не стандартизованном языке запросов, включённом в библиотеку объектно-реляционного отображения Hibernate. Hibernate и HQL были созданы до появления спецификации JPA. JPQL является подмножеством языка запросов HQL.

Примеры JPQL

JPQL запрос получения списка авторов сущности «Author», упорядоченных в алфавитном порядке, имеет вид :

SELECT a FROM Author a ORDER BY a.firstName, a.lastName

Запрос получения списка авторов, когда-либо опубликованных издательством «Publisher Press» :

SELECT DISTINCT a FROM Author a INNER JOIN a.books b WHERE b.publisher.name = 'Publisher Press'

JPQL поддерживает именованные параметры, которые начинаются с символа двоеточия ‘:’. Следующая функция, возвращающая список авторов с определенной фамилией, будет иметь следующий вид :

import javax.persistence.Query; import javax.persistence.EntityManager; import org.apache.commons.lang.StringUtils; . @SuppressWarnings(«unchecked») public List

Источник

Object Relational Mapping

После изучения JDBC у тебя скорее всего сложилось мнение, что работать с базой данных из Java-приложения — то еще удовольствие. А что если я скажу, что всю это работу можно сделать в 10 раз проще?

В чем главное преимущество языка SQL? Это декларативный язык — он описывает, что мы хотим получить, и совсем ничего не говорит о том, как это сделать. Как — это уже забота SQL-сервера.

Тот же подход можно использовать и при работе с базами данных.

В идеальном мире мы могли бы просто писать SQL-запросы к базе, а в ответ нам бы приходили готовые Java-объекты, ну или коллекции Java-объектов, если мы запросили несколько штук.

Что сказать, именно так подумали несколько ребят в 2000 году и решили написать свой ORM framework.

ORM расшифровывается как Object-Relational Mapping и по сути является маппингом Java-объектов на SQL-запросы.

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

Было три подхода к решению этой задачи, и выглядели они примерно так:

  1. Объект сам себя сохраняет в базу данных и обновляет свои поля на основе информации из БД.
  2. Объект умеет сохранять себя в базу данных, но никогда не выступает инициатором этого дела.
  3. Объект содержит только данные, и кто-то его сохраняет в базу данных и загружает из БД.

Изначально доминировал первый подход, тогда были популярны Application-сервера и Enterprise Java Beans. Был даже целый класс бинов, которые назывались Persistence EJB, которые умели себя сохранять в базу сами.

Но однажды все изменилось…

1.2 Появление Hibernate

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

Маппинг полей Java-классов и колонок в таблице в базе задавался с помощью XML-файла. И иногда они были довольно громоздкими. Ладно, кого я обманываю. Это были здоровенные полотна XML-кода. И ситуацию спасало только то, что 20 лет назад не было таких гигантских баз данных, как сейчас.

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

И подход ORM действительно ломает эту концепцию. Data-класс выставляет наружу свое внутреннее устройство, зато оперировать группами объектов разных типов стало значительно проще.

Серьезный прорыв случился после выхода Java 5 , когда в JDK появились две вещи:

Аннотации быстро вытеснили XML, и теперь прямо в Java-классе можно было легко указать все нужные настройки для маппинга Java-класса на таблицу в базе данных.

Прокси не так заметны для пользователя Hibernate, но их вклад был еще серьезнее. Когда ты запрашиваешь определённый объект или объекты у Hibernate, он просто возвращает тебе заглушку (proxy), и перехватывает все обращения к ее методам.

Это позволило реализовать различные механизмы Lazy Loading’а и подняло скорость и эффективность работы Hibernate на совсем заоблачный уровень для того времени. Hibernate стал не просто стандартом отрасли де-факто — его начали переводить на другие языки. Так, например для C# появился Framework NHibernate.

1.3 Появление JPA

За де-факто пришло и признание де-юре. Разработчики JDK решили создать спецификацию по тому, как правильно мапить объекты на таблицы в базе данных. Эта спецификация называется JPA — Java Persistence API.

Это именно спецификация. Она описывает, как все должно работать и какими аннотациями нужно отмечать различные части класса, если мы хотим, чтобы его объекты сохранялись в базу данных.

Такое ощущение, что ребята просто взяли за основу Hibernate и поменяли у него имена пакетов. Потому что все аннотации, которые были в Hibernate, почти один в один переехали в JPA.

На сегодняшний день Hibernate полностью реализует всю спецификацию JPA, а также некоторые дополнительные возможности, которые делают работу с ним еще комфортнее. Поэтому с точки зрения стандартизации можно сказать, что у Hibernate есть два набора функций:

  • JPA-стандарт
  • Hibernate Native API (дополнительная функциональность)

В официальной документации Hibernate это описывается так:

Но и на основе своего опыта, и после повторного прочтения документации по Hibernate я могу сказать, что JPA и Hibernate API совпадают на 95%. Это просто тождественные понятия.

1.4 Maven для Hibernate

Раз уж я так сильно расхвалил Hibernate, думаю, настало время перейти к работе с ним немного поплотнее.

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

  1. Открываешь ссылку.
  2. Долго на нее смотришь.
  3. Возвращаешься на JavaRush.
  4. Читаешь мои дальнейшие лекции.

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

Ну, а чтобы приступить к работе с Hibernate, тебе нужно добавить его в свой pom.xml. На сегодняшний день доступна уже 6-я версия Hibernate, а точнее 6.1.1, так что будем учиться работать с самой последней версией.

Просто добавь в свой pom.xml такие строки:

  org.hibernate hibernate-core 6.1.1.Final  

Если ты читаешь эту лекцию и за окном 2023+ год, тогда новую версию можно скачать тут.

Важно! Некоторые библиотеки, которые использует Hibernate, были исключены из JDK 11 и JDK 17, поэтому если у тебя возникают проблемы с запуском проекта, то добавь в него такие зависимости:

  jakarta.xml.bind jakarta.xml.bind-api 4.0.0  org.glassfish.jaxb jaxb-runtime 4.0.0  org.javassist javassist 3.29.0-GA  

Источник

Оцените статью