tags:

views:

92

answers:

3
+2  Q: 

Using enum as id

Using JPA, can we define an enum as id of an entity?

I've tried the following:

public enum AssetType {
   ....
}

@Entity
@IdClass(AssetType.class)
public class Adkeys {

   private AssetType type;

   @Id
   @Enumerated(EnumType.STRING)
   @Column(nullable = false)
   public AssetType getType() {
      return type;
   }

}

Using OpenJPA, it complains:

org.apache.openjpa.persistence.ArgumentException: The id class "class aa.AssetType" specified by type "class aa.Adkeys" does not have a public no-args constructor.

So my questions are:

  • should we able to use enum as id for an entity on JPA? (i.e. there is a bug in OpenJPA)
  • or do I make a mistake somewhere?
  • and is there any workaround for such problem?
+5  A: 

The JPA spec doesn't say this is possible:

2.1.4 Primary Keys and Entity Identity

The primary key (or field or property of a composite primary key) should be one of the following types: any Java primitive type; any primitive wrapper type; java.lang.String; java.util.Date; java.sql.Date. In general, however, approximate numeric types (e.g., floating point types) should never be used in primary keys. Entities whose primary keys use types other than these will not be portable.

If you really want to have a compile-time fixed number of records for a given entity, you can use a String or int primary key and assign it AssetType.FOO.name() or AssetType.FOO.ordinal()

And non-portable here means that some persistence provider may support other things, but it might not work for another provider. As with the enum - if the persistence provider has special support for it, that does not try to instantiate it, but rather processes it specially after checking if class.isEnum(), then it might work. But it seems your persistence provider doesn't do this.

Bozho
It doesn't say this is possible but doesn't say it is impossible either. It just says: 'Entities whose primary keys use types other than these will not be portable'. In fact, it doesn't also say that a class can be used as primary key but it's possible.
nanda
that's another thing - an embeddable id. see my update for the portability part.
Bozho
so I guess this is a valid request for an enhancement, don't you think?
nanda
+2  A: 

No, you can't use enums as ID because JPA doesn't allow to define your own mapping for ID columns (they must be int or long or something that JPA can create with new).

IDs must not be the business key (in your case: the type). Using the business key as an ID is a common mistake in DB designs and should be avoided because it will cause all kinds of problems later.

Add an independent ID column to solve the problem.

Aaron Digulla
I'm working with old database. It might be not good design but it's there. The enum is just a bunch of rigid value.
nanda
A: 

Do you really want to do this? This construct doesn't allow changing the database enum keys without updating the enum in the code (fail on load), nor the other way around (constraint failure). Why don't you just create an AssetType table with int pk and name, and make the Adkeys have a foreign key to AssetType.id as pk?

You can load the AssetTypes from the db on startup if you need to enumerate them in your app.

disown
I'm working with old database. Of course I can change it but it might be problematic. The enum is just a bunch of rigid value.
nanda