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

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

Создадим базовое веб-приложения на связке Spring Boot 3 + Hibernate + PostgreSQL

Создадим два перечисления (лучше каждый в своём файле):

Создадим класс предметной области следующего содержания:

Поле status мы пометили аннотацией @Enumerated с параметром value = EnumType.STRING. Это означает, что при сохранении данных в БД будет сохранятся строковое значение enum’а. То есть, если status будет равен Status.GRATA, то в БД будет сохранена строка «GRATA».

Поле country помечено аннотацией @Enumerated с value = EnumType.ORDINAL. Это значит, что в БД будет сохранятся порядковый номер перечисления, начия с нуля. То есть в нашем случае для RUSSIA будет сохраняться 0, а для CHINA — 1.

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

В любом случае рефакторинг перечислений, используемых в классах предметной области, это всегда определённые риски рассинхронизации с данными в БД.

Создадим репозиторий:

Создадим тест:

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

Посмотрим, как это выглядит собственно в БД:

Для поля country была создана колонка типа smallint, а для status — varchar(255). Соответственно в таблице в колонку country сохранилось числовое значение перечисления, а в status — строковое. Всё как мы и обозначили в наших аннотациях над полями класса предметной области Person.