JPA Enum Наследование - PullRequest
       4

JPA Enum Наследование

0 голосов
/ 08 января 2019

У меня есть интерфейс с именем 'Category' и 4 enum, реализующих этот интерфейс. Эти перечисления делятся на категории и имеют разные типы. Пример:

#Interface
interface BillCategory

#Enum 1
public enum GroceryPurchase implements BillCategory {
  VEGAN,  
  VEGETARIAN,
  PESCITARIAN,
  FLEXITARIAN, 
  OMNIVORE


#Enum 2
enum ElectronicPurchase implements BillCategory{ 
 SMARTPHONE, HARDWARE, SOFTWARE }

Я добавил поле в класс сущности.

private BillCategory billCategory;

И когда я запускаю Spring Environemnt, я получаю следующую ошибку Hibernate / JPA:

Invocation of init method failed; nested exception is javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory; nested exception is org.hibernate.MappingException: Could not determine type for: net.wizypay.wizypay.bill.model.BillCategory, at table: bill_entity, for columns: [org.hibernate.mapping.Column(bill_category)]

Как я могу решить эту проблему? Я не хочу сводить перечисления к одному. Есть ли лучший подход? Или просто невозможно сохранить такие данные.

Ответы [ 2 ]

0 голосов
/ 08 января 2019

В вашем разуме две противоречивые цели, и вы пытаетесь удовлетворить обе, не осознавая этого.

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

Когда вы используете JPA для сопоставления отношений с объектами Java - вы стремитесь централизовать код, который строит и сериализует ваши объекты. Обратите внимание, что - если вы не используете отражение - этот код должен зависеть от всех типов, которые вы используете, потому что он должен иметь возможность создавать все значения. В частности, если в базе данных хранится строка с надписью «APPLE», ей необходимо знать, является ли она Computer.APPLE или Fruit.APPLE.

Если вы не используете рефлексию - сохраните имя рассматриваемого класса - это невозможно сделать в общем виде. И если вы используете отражение, вы теряете другую вещь: абстракцию. Внезапно ваши данные базы данных зависят от вашей реализации Java.

Вы должны:

  • принять невозможность того, что вы пытаетесь достичь
  • Приоритет ваших требований

В зависимости от ваших требований, одним чистым решением будет создание конвертера с методами, аналогичными:

  BillCategory fromString(String category);
  String fromCategory(BillCategory category);

Это обеспечит чистоту базы данных и кода Java независимо от перечислений. По стоимости двух брутто-свитчей в одном месте.

0 голосов
/ 08 января 2019

Да, не уверен, как Smartphone НЕ Hardware, но все в порядке. Вот как я бы это сделал (не уверен, что если я откажусь от того, что вам действительно нужно сейчас). Сделайте BillCategory перечисление. Добавьте приватные поля PurchaseType (это может быть также другое перечисление, содержащее такие значения, как GroceryPurchase или ElectronicPurchase) и Category (это String и соответствует имени перечисления). Это должно решить вашу проблему с Hibernate.

Код, иллюстрирующий, что я имею в виду:

enum BillCategory {
    VEGAN("VEGAN", PurchaseType.GroceryPurchase), VEGETARIAN("VEGETARIAN",
            PurchaseType.GroceryPurchase), SMARTPHONE("SMARTPHONE", PurchaseType.ElectronicPurchase);

    private String category;
    private PurchaseType type;

    BillCategory(String category, PurchaseType type) {
        this.category = category;
        this.type = type;
    }

    public String getCategory() {
        return category;
    }

    public void setCategory(String category) {
        this.category = category;
    }

    public PurchaseType getType() {
        return type;
    }

    public void setType(PurchaseType type) {
        this.type = type;
    }

}

enum PurchaseType {
    ElectronicPurchase, GroceryPurchase;
}

Затем вы также должны аннотировать private BillCategory billCategory; в своем классе сущности чем-то вроде @Enumerated(EnumType.ORDINAL) или каким-либо другим EnumType, в зависимости от того, как вы хотите, чтобы оно было сохранено в базе данных

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...