If there's an enum
(this is all java 5)
public static enum Type {
TYPE_1(1);
private int i;
private Type(int i) {this.i = i;}
}
you can't do entityManager.merge( Type.TYPE_1 ), because merge returns a persisted copy of that object and requires a default constructor.
Even if you add
it would fail.
The only way to add the possible values is with persist:
for( Type type : Type.values() ) {
entityManager.persist( type );
}
Unfortunately I don't know of a shortcut for that operation - it seems logical all enum values to be in the DB, but are not there by default.
So what happens if there's an object
public class Subscription {
// Cascading for all operations
protected Type type;
}
and one wants to persist an object like that:
entityManager.merge( new Subscription() ); // would work only with step1
entityManager.merge( new Subscription() ); // without step1: "InstantiationException: No default constructor for entity
So the conclusion is:
It's relatively easy to use enums as @Entities as long as on DB init all the enum values are preloaded in the DB (step1).
UPDATE:
What I wrote so far is true, BUT:
Even if one can persist enum, one cannot get them back, because of the aforementioned problem with the default constructor.
I was thinking of the doing the type-safe enum design pattern myself (as it was done pre- java 5): useless supplying a default .ctor prevents having a small number of instances - so again no good. Maybe if the .equals() and .hashcode() are rewritten this could work (but with a larger number of instances and a small number of different hashcodes) - just thought of it, may or may not work. One has to think about @Enumerated (JPA) or about Enum.name() and enum.ordinal() - still it does not look achievable.
There is an ugly solution of which I shall speak tomorrow because I want to go home !!!.
UPDATE: The solution: (be warned it's really ugly).
There should be an @Entity with an int (or whatever actually) @Id.
Then there should be the enum with a private property, whose type should be the @Id of the previous class. There should be a getter of that property
The getter() and setter() of the @Entity should be with the enum's type and in the getter and the setter the wrapping between the enum and it's int (or whatever actually) should occur.
Examples when I get back from lunch.
UPDATE: Example
public enum Gender {
Male(0),
Female(1);
private int value;
private Gender(int value) {
this.value = value;
}
public getValue() {
return this.value;
}
}
@Entity
public class Entity1 {
@Id
private int gender;
// ... other properties
public Gender getGender() {
return Gender.valueof(this.gender);
}
public Gender setGender( Gender gender) {
this.gender = gender.getValue();
}
// ... other stuff.
}
Yes, I know - it's ugly, but this is the best I know.