Маппинг Enum

@Enumerated

@Enumerated(EnumType.STRING)
@Column(nullable = false)
private OrderStatus status;
  • ORDINAL хранит порядковый номер. Перестановка или вставка значения меняет смысл существующих строк.
  • STRING хранит имя константы. Безопаснее к порядку, но переименование требует миграции.

EnumType.STRING обычно лучше, однако имя Java-константы становится частью формата данных.

Стабильный код через converter

Если БД должна хранить независимый код, используется AttributeConverter:

public enum Status {
    NEW("N"), DONE("D");
 
    private final String code;
}
 
@Converter(autoApply = true)
public class StatusConverter
        implements AttributeConverter<Status, String> {
    public String convertToDatabaseColumn(Status value) {
        return value == null ? null : value.code();
    }
 
    public Status convertToEntityAttribute(String code) {
        return code == null ? null : Status.fromCode(code);
    }
}

Не следует одновременно применять к одному атрибуту @Enumerated и converter.

Ограничения

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

Вопросы для повторения

  1. Почему ORDINAL опасен? Порядок enum становится контрактом сохранённых данных.
  2. Достаточно ли STRING для стабильности? Нет, переименование константы меняет контракт.
  3. Когда нужен converter? Когда формат БД должен быть независим от имени Java enum.
  4. Как добавить новое значение безопасно? Сначала расширить допустимый формат/читателей, затем начать запись нового кода.

Связано: Маппинг Hibernate, Аннотация Column.