Колонка-enum, замапленная через @Enumerated(EnumType.STRING), хранит в БД строку с именем значения. Если убрать значение из Java-enum, а в таблице остались строки с этим именем — Hibernate при чтении (гидратации) сущности падает:
IllegalArgumentException: No enum constant <EnumClass>.<OLD_VALUE>
Сущность перестаёт читаться, и ломается всё, что её грузит из БД.
Правило
Перед удалением значения из enum — мигрировать все строки в таблице (во всех средах: dev/stage/prod) на новое допустимое значение. Удалять значение из кода только после того, как в БД не осталось строк со старым именем.
Подводные камни миграции
- Не матчить по хардкод-id.
UPDATE ... WHERE id = '<...>'чинит только перечисленные строки. Строки, созданные приложением (случайные id), останутся со старым значением. Матчить по содержимому:UPDATE ... SET type = 'NEW' WHERE type = 'OLD'. - Проверять все среды. Значение, отсутствующее в dev (где данные — seed), может остаться в stage/prod, где строки заводились приложением или вручную.
Почему именно так
@Enumerated(STRING) (в отличие от ORDINAL) хранит имя константы, а не порядковый номер — это устойчиво к перестановке значений, но строго к их набору: маппинг строки в enum идёт через Enum.valueOf, который бросает исключение на неизвестном имени.
Похожий класс гоч маппинга — Дублирование значений при использовании @ElementCollection и @OneToMany.