В вашем разуме две противоречивые цели, и вы пытаетесь удовлетворить обе, не осознавая этого.
Когда вы разделяете константы на множество перечислений, реализующих один и тот же интерфейс, вы стремитесь к расширяемости: вы удаляете зависимость из кода, используя перечисления для самих перечислений. Вы можете создавать новые перечисления, не нарушая существующий код.
Когда вы используете JPA для сопоставления отношений с объектами Java - вы стремитесь централизовать код, который строит и сериализует ваши объекты. Обратите внимание, что - если вы не используете отражение - этот код должен зависеть от всех типов, которые вы используете, потому что он должен иметь возможность создавать все значения. В частности, если в базе данных хранится строка с надписью «APPLE», ей необходимо знать, является ли она Computer.APPLE или Fruit.APPLE.
Если вы не используете рефлексию - сохраните имя рассматриваемого класса - это невозможно сделать в общем виде. И если вы используете отражение, вы теряете другую вещь: абстракцию. Внезапно ваши данные базы данных зависят от вашей реализации Java.
Вы должны:
- принять невозможность того, что вы пытаетесь достичь
- Приоритет ваших требований
В зависимости от ваших требований, одним чистым решением будет создание конвертера с методами, аналогичными:
BillCategory fromString(String category);
String fromCategory(BillCategory category);
Это обеспечит чистоту базы данных и кода Java независимо от перечислений. По стоимости двух брутто-свитчей в одном месте.