Сохраняющиеся данные, подходящие для перечислений

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

public enum Status {
    ACTIVE(10, "Active");
    EXPIRED(11, "Expired");
    /* other statuses... */

    /* constructors, getters, etc. */
}

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

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

Моим преимуществом является второй вариант, хотя мой администратор баз данных утверждает, что нашим конечным пользователям может потребоваться доступ к необработанным данным для создания отчетов, а не к сохранению статусов приведет к неполной модели данных (контр-аргумент: это можно решить с документацией).

Существует ли соглашение, которое большинство людей здесь используют? Каковы опыты людей с каждым и есть ли другие альтернативы?

Edit:

Подумав об этом некоторое время, моя настоящая упорная борьба связана с обработкой значений id, привязанных к статусам в базе данных. Эти значения будут вставлены в качестве данных по умолчанию при установке приложения. На этом этапе у них будут идентификаторы, которые можно использовать в качестве внешних ключей в других таблицах. Я чувствую, что мой код должен знать об этих идентификаторах, чтобы я мог легко получить статусные объекты и назначить их другим объектам. Что мне делать с этим? Я мог бы добавить еще одно поле, например "код", чтобы посмотреть на вещи, или просто посмотреть статусы по имени, что нехорошо.

Ответ 1

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

Если вы ожидаете много значений перечисления, вы можете создать статическое сопоставление HashMap<String,MyEnum> для быстрого перевода.

Не сохраняйте фактическое имя перечисления (т.е. "АКТИВНО" в вашем примере), поскольку это легко реорганизовывается разработчиками.

Ответ 2

Я использую сочетание трех подходов, которые вы задокументировали...

Используйте базу данных в качестве авторитетного источника для значений Enum. Храните значения в таблице "code". Каждый раз, когда вы создаете, создайте файл класса для Enum, который будет включен в ваш проект.

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

Ответ 3

Джошуа Блох дает отличное объяснение перечислений и как их использовать в своей книге " Эффективная Java, второе издание" (стр .147 )

Здесь вы можете найти всевозможные трюки, как определить свои перечисления, сохранить их и как быстро сопоставить их между базой данных и вашим кодом (стр .154).

Во время разговора на Jazoon 2007 Блох дал следующие причины использовать дополнительный атрибут для перечисления перечислений в поля БД и обратно: перечисление является константой, а код - нет. Чтобы убедиться, что редактор, редактирующий источник, не может случайно сломать отображение БД путем переупорядочения перечислений или переименования, вы должны добавить конкретный атрибут (например, "dbName" ) в перечисление и использовать его для его сопоставления.

Enums имеют внутренний идентификатор (который используется в операторе switch()), но этот идентификатор изменяется при изменении порядка элементов (например, путем сортировки их или добавления элементов в середине).

Таким образом, лучшим решением является добавление метода toDB() и fromDB() и дополнительного поля. Я предлагаю использовать короткие, читаемые строки для этого нового поля, поэтому вы можете декодировать дамп базы данных, не просматривая перечисления.

Ответ 4

Пока я не знаком с идеей "атрибутов" в Java (и я не знаю, на каком языке вы работаете), я обычно использовал идею таблицы кодов (или таблиц, специфичных для домена), и Я присвоил свои значения enum более конкретным данным, таким как читаемые пользователем строки (например, если мое значение перечисления является NewStudent, я бы присвоил его "New Student" в качестве отображаемого значения). Затем я использую Reflection для проверки данных в базе данных и вставки или обновления записей, чтобы привести их в соответствие с моим кодом, используя фактическое значение перечисления в качестве идентификатора ключа.

Ответ 5

То, что я использовал в нескольких случаях, - это указать перечисление в коде и представление хранилища на уровне сохранения (DB, файл и т.д.), а затем использовать методы преобразования для сопоставления их друг с другом. Эти методы преобразования нужно использовать только при чтении или записи в постоянном хранилище, и приложение может использовать безопасные перечисления типа везде. В методах преобразования я использовал инструкции switch для отображения. Это позволяет также генерировать исключение, если новое или неизвестное состояние должно быть преобразовано (обычно из-за того, что приложение или данные новее другого, а новые или дополнительные состояния были объявлены).

Ответ 6

Если есть хотя бы небольшой шанс, что список значений нужно будет обновить, а не 1. В противном случае это будет 3.

Ответ 7

Ну, у нас нет администратора баз данных, поэтому мы предпочитаем вариант 2).

Мы просто сохраняем значение Enum в базе данных, а когда мы загружаем данные из базы данных и в наши объекты домена, мы просто приводим целочисленное значение в тип перечисления. Это позволяет избежать любой из головных болей синхронизации с вариантами 1) и 3). Список определяется один раз - в коде.

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

Ответ 8

В вашей базе данных первичный ключ этой таблицы "домен" не должен быть числом. Просто используйте varchar pk и столбец описания (для целей вашего dba). Если вам нужно гарантировать порядок ваших значений, не полагаясь на алфавитный sor, просто добавьте числовой столбец с именем "порядок" или "последовательность".

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

Если вы сделаете это слишком много, создайте script, чтобы сгенерировать код установки/декларации.