Reputation: 1718
I have an interface called 'Category' and 4 enum implementing this interface. Those enums are decided in categories and have different types in it. Example:
#Interface
interface BillCategory
#Enum 1
public enum GroceryPurchase implements BillCategory {
VEGAN,
VEGETARIAN,
PESCITARIAN,
FLEXITARIAN,
OMNIVORE
#Enum 2
enum ElectronicPurchase implements BillCategory{
SMARTPHONE, HARDWARE, SOFTWARE }
I aded the field to an entity class.
private BillCategory billCategory;
And when I start the Spring Environemnt I get the following Hibernate/JPA error:
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)]
How can I solve this problem? I do not want to summarise the enums to one. Is there a better approach? Or just impossible to persist such data.
Upvotes: 3
Views: 1608
Reputation: 6435
Alrght, not sure how Smartphone
is NOT Hardware
, but okay. Here is how I would do it (Not sure if I discard something you actually need now). Make BillCategory
an enum. Add private fields PurchaseType
(this could also be another enum containing values like GroceryPurchase
or ElectronicPurchase
) and Category
(this is String and matches the enum name). That should solve your problem with hibernate.
Code illustrating what I mean:
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;
}
You should then also annotate private BillCategory billCategory;
in your entity class with something like @Enumerated(EnumType.ORDINAL)
, or some other EnumType
, depending on how you want it to be saved in the database
Upvotes: 1
Reputation: 12495
You have two conflicting goals in your mind and try to satisfy both, without realizing it.
When you split constants into many enums implementing the same interface, you are aiming for extensibility: you remove the dependency from the code using enums to the enums themselves. You are free to create new enums without breaking any existing code.
When you are using JPA to map from the relations into Java objects - you aim for centralizing the code that builds and serializes your objects. Note that - unless you are using reflection - this code must depend on all the types you are using, because it needs to be able to build all the values. Specifically, if the database stores a string that says "APPLE", it will need to know if it's Computer.APPLE or Fruit.APPLE.
Unless you use reflection - store the name of the class in question - it's impossible to do it in a general way. And if you use reflection, you loose another thing: abstraction. Suddenly your database data is dependent on your Java implementation.
You must:
Depending on your requirements, one clean solution would be to build a converter with methods along the line of:
BillCategory fromString(String category);
String fromCategory(BillCategory category);
This will keep both the database clean and the Java code independent from enums. At the cost of two gross switches in a single place.
Upvotes: 2