Архив рубрики: Hibernate

Отображение в структуру БД иерархии наследования Java в одну таблицу для всех наследников.

Классы сущностей Java могут иметь иерархическую структуру и существует ряд стратегий отображения этой структуры в БД. Одной из стратегий является отображение всех наследников в одну таблицу по имени предка.

То есть, если классы Client и Employee наследуют класс Person, то Hibernate создаёт одну таблицу PERSON, в которой хранит данные, отображённые как из объектов класса Client, так и из Employee.

Такая таблица получается не нормализованной и вынуждена допускать то или иной количество nullable полей, что имеет свои недостатки и может быть неприемлемым. Однако у этого похода есть свои преимущества. В одной таблице хранятся данные о различных объектах предметной области, что позволяет делать выборку разных объектов по общим полям. Это, вероятно, самый быстрый способ создавать полиморфные списки объектов типа List<Person>, делая выборку из БД.

Читать далее

Отображение в структуру БД иерархии наследования Java по принципу «отдельная таблица на каждый конкретный класс» с учётом полиморфизма с помощью Hibernate

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

То есть, если классы Client и Employee наследуют класс Person, то Hibernate создаёт для каждого отдельную таблицу, при этом нам становится доступно использование единого репозитория PersonRepository, который будет в одном запросе делать выборку из обеих таблиц (через union) и, как следствие, легко формировать списки типа List<Person>.

Читать далее

Отображение в структуру БД иерархии наследования Java без учёта полиморфизма с помощью Hibernate

Классы сущностей Java могут иметь иерархическую структуру и существует ряд стратегий отображения этой структуры в БД. Самой простой стратегией является отображение каждого конечного конкретного класса в отдельную таблицу с полным игнорированием полиморфных отношений.

То есть если классы Client и Employee наследуют класс Person, то Hibernate создаёт для каждого отдельную таблицу и при этом тот факт, что оба класса наследуют Person для Hibernate не будет иметь значения. Hibernate не будет способен искать объекты типа Person, составлять и возвращать из БД списки типа Person, в которых были бы смешаны данные из двух таблиц. Он будет работать с CLIENT и EMPLOYEE только как с абсолютно не связанными таблицами.

Читать далее

Конвертация типа колонки, создаваемой для поля встраиваемого (@Embeddable) класса в Hibernate.

Классы-значения имеют свой набор полей и при встраивании в класс-сущность каждому такому полю будет создана колонка соответствующего типа, например, VARCHAR для полей типа String, BIGINT для полей типа Long.

Типы создаваемых колонок можно поменять с помощью конвертеров не только для полей класса-сущности, но и для полей встраиваемых классов.

Читать далее

Произвольное преобразование Java типов в типы данных конкретной СУБД с помощью интерфейса javax.persistence.AttributeConverter в Hibernate

Мы привыкли использовать задействованные по умолчанию в Hibernate преобразования Java типов в соответствующие типы нашей СУБД. Так для полей типа java.lang.String создаётся колонка типа VARCHAR, для java.lang.Long — BIGINT (или аналоги специфичные для конкретного вендора).

При этом в Hibernate есть возможность создавать собственные конвертеры, с помощью которых можно преобразовывать данные собственных типов в стандартные Java типы (например, в String), чтобы Hibernate мог их сохранить, а затем и восстановить из колонок соответствующих типов. Например, наш кастомный тип FullName может быть конвертирован в String и сохранён в поле типа VARCHAR.

Читать далее

Переопределение параметров полей встраиваемых @Embeddable классов с помощью аннотаций @Embedded и @AttributeOverride в Hibernate

При создании колонок класса-сущности для сохранения значений классов-значений можно переопределить параметры колонок, описанные в помеченных аннотацией @Embeddable классах-значениях. Можно изменить имена колонок и их всевозможные ограничения.

Допустим класс Person содержит поле Address address. Класс Address помечен @Embeddable и хранит данные своих полей в соответствующих колонках таблицы PERSON. Но сами настройки полей указаны в классе Address. Так вот эти настройки легко переопределяются в классе Person.

Читать далее

Сохранение данных нескольких классов предметной области в одну строку БД с помощью аннотации @Embeddable в Hibernate

В объектно-реляционном отображении различают сущности (entity) и значения (value). Сущности — это данные, имеющие свой жизненный цикл, а с ним и собственную таблицу с id в БД. Значения не имеют собственного жизненного цикла и, как правило, сохраняются в одну строку с сущностью, от которой зависят.

Так, например, адрес может с одной стороны быть представлен отдельным классом в Java, но в БД храниться в виде соответствующих колонок в таблице PERSON. Если адрес у каждого человека один и существует только в привязке к конкретному человеку, то нет никакой необходимости заводить для адресов отдельную таблицу ADDRESS и делать связь один к одному между таблицами PERSON и ADDRESS. Достаточно хранить все данные в PERSON.

Чтобы при этом было возможно в Java-коде пользоваться для адресов отдельным классом, мы можем использовать аннотацию @Embeddable над классом Address.

Читать далее

Объектно-реляционное отображение enum’ов Java в колонки БД и обратное отображение данных БД в enum пока классов предметной области с помощью аннотации @Enumerated в Hibernate

Классы предметной области в Java могут содержать поля перечисляемых типов (enum’ы) и данные этих полей, разумеется должны сохранятся в БД и восстанавливаться из БД. В силу естественных ограничений в БД может быть сохранено либо числовое значение enum’а, соответствующее его порядку, либо его строковое значение. Отвечает за это аннотация @Enumerated.

Читать далее

Использование аннотации @Temporal для уточнения типа колонки, создаваемой Hibernate’ом для полей типа java.util.Date и java.util.Calendar

При автоматическом создании схемы базы данных на основании аннотированных классов предметной области мы можем уточнить тип данных в колонке, которая соответствует полям типа java.util.Date и java.util.Calendar. Поля типа Date хранят информацию о количестве миллисекунд с т.н. начала эпохи. Но такой формат может быть избыточным. Возможно в реальности нас интересует только дата или только время, возможно и то и другое. Соответственно в БД мы хотели бы видеть колонку либо типа DATE, либо типа TIME, либо TIMESTAMP. Аннотация @Temporal позволяет уточнить, какого именно типа создавать колонку для конкретного поля типа Date.

Отметим, что тип java.util.Date (Calendar) является устаревшим. Он хранит время с точностью до миллисекунды (три знака после запятой). Современные типы данных, например, java.time.LocalDateTime хранят время с точностью до микросекунды (шесть знаков после запятой).

Читать далее

Использование в Hibernate аннотации @ColumnDefault, чтобы задать значение по умолчанию колонок БД.

Аннотация @ColumnDefault надо полем класса предметной области заставит Hibernate создать для этого поля колонку в БД со значением по умолчанию, которое передаёт параметром в эту аннотацию. Кроме того, с помощью параметра GenerationTime.INSERT аннотации @Generated можно определить, возможно ли будет переопределять значение по умолчанию при вставке или оно всегда будет одним и тем же, когда создаётся новая запись в таблице.

Читать далее