В стандартном варианте использования JPA для атрибутов типа enum
в базе данных хранится целое число, получаемое методом ordinal()
этого перечисления. Такой подход может привести к следующим проблемам при эксплуатации и развитии системы:
-
при появлении в БД значения, не равного ни одному
ordinal
значению перечисления, экземпляр сущности нельзя загрузить вообще; -
невозможно ввести новое значение между имеющимися, что актуально при использовании сортировки по значению перечисления (order by).
Чтобы решить эти проблемы, в подходе CUBA предлагается отвязать значение, хранимое в БД, от ordinal
перечисления. Для этого необходимо поле класса сущности объявлять с типом, хранимым в БД (Integer
или String
), а методы доступа (getter / setter) создавать для типа самого перечисления.
Например:
link:../../../../../source/common/enum_1.java[role=include]
При этом сам класс перечисления может выглядеть следующим образом:
link:../../../../../source/common/enum_2.java[role=include]
Для правильного отражения в метаданных класс перечисления, используемый в качестве типа атрибута сущности, должен реализовывать интерфейс EnumClass
.
Как видно из примеров, для атрибута grade
в БД хранится значение типа Integer
, задаваемое полем id
перечисления CustomerGrade
, а конкретно 10
, 20
или 30
. В то же время прикладной код и метаданные работают с самим типом CustomerGrade
через методы доступа, которые и осуществляют конвертацию.
При наличии в поле БД значения, не соответствующего ни одному значению перечисления, метод getGrade()
просто вернет null
. Для ввода нового значения, например, HIGHER
, между HIGH
и PREMIUM
, достаточно добавить это значение в перечисление с идентификатором 15
, при этом сортировка по полю Customer.grade
останется верной.
Тип поля Integer
удобно использовать в случаях, когда необходим упорядоченный список констант, подлежащий сортировке, например, в запросах JPQL и SQL (>
, <
, >=
, ⇐
, order
by
), кроме того, он имеет незначительное преимущество перед String
в плане производительности формата хранения и занимаемого места. С другой стороны, значения типа Integer
сами по себе неочевидны и могут затруднять отладку и интерпретацию результатов запросов, они неудобны в работе с голыми данными и сериализованными форматами. Если отношение упорядочения между константами не требуется, удобнее использовать тип String
.
Перечисления могут быть созданы в CUBA Studio в секции Data Model > New > Enumeration. Чтобы использовать перечисление в качестве атрибута сущности, в редакторе атрибута нужно выбрать ENUM
в поле Attribute type и класс перечисления в поле Type. Значениям перечисления могут быть сопоставлены локализованные названия для отображения в пользовательском интерфейсе приложения.