JPA Enum ORDINAL vs STRING - PullRequest
       31

JPA Enum ORDINAL vs STRING

39 голосов
/ 22 июля 2011

Можно определить перечисления в JPA, используя

@Enumerated(EnumType.ORDINAL)

или

@Enumerated(EnumType.STRING)

Интересно, каковы преимущества и недостатки этих двух определений?

Я слышал, что ORDINAL работает лучше (быстрее), чем STRING с EclipseLink.
Это правда?

Ответы [ 8 ]

65 голосов
/ 22 июля 2011

Я всегда иду STRING.

Скорость редко является самой важной проблемой - удобочитаемость и удобство обслуживания больше важно.

Я использую STRING, потому что этонамного проще вручную проверить строки из базы данных, но, что более важно, я могу сделать две вещи, не касаясь базы данных, ORDINAL не может обработать:

  1. Я могу изменить порядок моих перечислений
  2. Я могу вставить новые перечисления в середину списка перечислений

Оба эти изменения изменят порядковые значенияиз перечислений, уже используемых в базе данных, тем самым нарушая существующие данные, если вы используете ORDINAL.

Если вы изменяете значение перечисления (не так часто), обрабатывать его просто:

UPDATE table SET enum_column = 'NEW_ENUM_NAME' where enum_column = 'OLD_ENUM_NAME';
16 голосов
/ 22 июля 2011

Вероятно, что ORDINAL более эффективно, но это незначительно. Есть несколько минусов к ORDINAL:

  • менее читабельно в базе данных
  • если вы переупорядочите определения enum, база данных будет непоследовательной.

С помощью STRING вы не можете переименовать свои перечисления.

Выберите один из них и используйте его во всем приложении - будьте последовательны.

Если ваша база данных будет использоваться другими клиентами / языками - используйте STRING, она более читабельна.

3 голосов
/ 21 июля 2017

Я предпочитаю использовать Ordinal, но на самом деле зависит от использования .

Например:

У вас есть перечисление, чтобы сохранить все ваши пользовательские состояния, в этом случае порядок не имеет значения, и вы можете добавить больше состояний в будущем (Лучшее использование -@Enumerated(EnumType.ORDINAL)):

public enum UserStates { ACTIVE, DELETED, PENDING }

Но теперь у вас есть перечисление, чтобы спасти Планеты в Солнечной системе (Лучшее использование @Enumerated(EnumType.STRING)):

public enum Planets {MERCURY,VENUS,EARTH,MARS,JUPITER,SATURN,URANUS,NEPTUNE,PLUTO,NINE}

Теперь подумайте, чтовы хотите изменить порядок своих планет, с @Enumerated(EnumType.ORDINAL) вы не можете, потому что ваша база данных не может знать новый порядок в вашем файле Java.

Вы можете изменить порядок своих Планет, используя @Enumerated(EnumType.STRING), потому что ваша Планета связана с именем перечисления, а не с порядком перечисления.

В любом случае, вы можете изменить свои @Enumerated(EnumType.STRING) перечисления, потому что они связаны с порядком, но вы не можете изменить свои @Enumerated(EnumType.STRING) перечисления, потому что они будут использовать как новые перечисления.

Stringтипы более читабельны в базе данных, но будут иметь больший размер, чем порядковые данные.Может быть полезно, если база данных используется большим количеством клиентов, но лучше иметь хорошую документацию по программному обеспечению, чем сохранять 1000 раз «ЗЕМЛЯ», чем «4»

USERSTATE
------------
ID | STATE |
------------
1 | 1
2 | 2
3 | 1

Planets
------------
ID | Name |
------------
1 | EARTH
2 | EARTH
3 | MARS
4 | EARTH
2 голосов
/ 12 января 2018

Это хороший вопрос.В прошлом я использовал String, но сегодня я предпочитаю обычно Ordinal.

Основной недостаток для String - для администраторов баз данных.Со строкой они не имеют представления о возможных значениях столбца, поскольку эта информация находится в коде приложения.Администратор базы данных может иметь только некоторое представление о возможных значениях, группирующих существующую информацию в таблице, но он никогда не будет уверен в других возможных значениях или в случае добавления новых значений, пока приложение не вставит их в таблицу.

В Порядке у вас та же проблема.Но мое предпочтение Ordinal пришло к решению проблемы DBA, которая кажется естественной для базы данных.Вы создаете новую таблицу для отображения возможных значений перечислителя в базе данных с внешним ключом между столбцом (порядковым значением перечисления) и этой новой таблицей.Эта стратегия описана и реализована здесь .

Что касается проблемы, связанной с тем, что кто-то может переупорядочить Перечислитель и сломать систему, простой модульный тест может решить эту проблему и гарантировать, что никто не будет переупорядочиватьих без хорошего предупреждения.Эта же идея действительна при переименовании Enumerator.Таким образом, переименование (в String) или изменение порядка (в Ordinal) случайно не является сильным аргументом против подхода String или Ordinal.

Кстати, разработчикам больше нужно переименовывать, чем переупорядочивать Enumerator, так что это еще один положительный момент использования Ordinal.

Итак, с этим подходом вы решаете основную проблемуПорядкового номера (теперь он доступен для чтения), информация будет занимать меньше места в базе данных, и ваш администратор базы данных будет счастлив.

0 голосов
/ 22 мая 2019

Я бы предпочел EnumType.STRING.Недостатком EnumType.ORDINAL является влияние времени и желание сохранять перечисления в логическом порядке.С EnumType.ORDINAL любые новые элементы enum должны быть добавлены в конец списка, иначе вы случайно измените значение всех ваших записей.пожалуйста, проверьте эту ссылку: https://tomee.apache.org/examples-trunk/jpa-enumerated/

0 голосов
/ 18 апреля 2019

Здесь много полезных советов, но я просто хотел добавить что-то, чего еще не видел:

Независимо от того, какое решение вы выберете, не забудьте добавить большое жирное предупреждение в верхней части вашего класса enum, в котором сказано, что следует использовать. Надеюсь, другие разработчики увидят, что вы сделали это, и воспользуетесь тем же методом для сохранения enum.

0 голосов
/ 08 апреля 2017

Это зависит от вашего приложения, если есть больше шансов, что вы добавите больше перечислений, используйте тип String, если есть больше шансов, что вы измените имя своих перечислений, используйте Ordinal.

0 голосов
/ 27 января 2012

Вы действительно уверены, что база данных, удобочитаемая человеком, - это то, что вам нужно? Хранение строкового значения - пустая трата места. Единственным компромиссом с удобочитаемостью может быть использование @Enumerated (STRING) и столбца базы данных карты в качестве ENUM (если вы используете mysql ... Я предполагаю, что другие dbms имеют что-то похожее), но это настоящая боль, когда вам нужно изменить имена перечислений.

...