2010-09-15 17 views
5

Utilizzando JPA, possiamo definire un enum come id di un'entità?Utilizzo di enum come id

ho provato la seguente:

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; 
    } 

} 

Utilizzando OpenJPA, si lamenta:

org.apache.openjpa.persistence.ArgumentException: La classe id "class aa.AssetType" specificato per tipo "class aa.Adkeys" non ha un costruttore no-args pubblico.

Quindi le mie domande sono:

  • dovremmo in grado di utilizzare enum come id per un'entità su JPA? (cioè c'è un bug in OpenJPA)
  • o faccio un errore da qualche parte?
  • e c'è qualche soluzione per tale problema?
+0

@Nathan: Quindi deve essere un bug. –

risposta

7

Le specifiche APP non dire che questo è possibile:

2.1.4 chiavi primarie ed Entity Identità

La chiave primaria (o il campo o la proprietà di una chiave primaria composta) dovrebbe essere uno dei seguenti tipi: qualsiasi tipo di primitivo Java; qualsiasi tipo di wrapper primitivo; java.lang.String; java.util.Date; java.sql.Date. In generale, tuttavia, i tipi numerici approssimativi (ad es. I tipi a virgola mobile) non dovrebbero mai essere usati nelle chiavi primarie. Le entità le cui chiavi primarie utilizzano tipi diversi da questi non saranno portatili.

Se si vuole veramente avere un tempo di compilazione numero di record fisso per una data entità, è possibile utilizzare una chiave primaria String o int e assegnarlo AssetType.FOO.name() o AssetType.FOO.ordinal()

e non portatili qui mezzi che qualche provider di persistenza può supportare altre cose, ma potrebbe non funzionare per un altro provider. Come con l'enum, se il provider di persistenza ha un supporto speciale, non tenta di istanziarlo, ma piuttosto lo elabora appositamente dopo aver verificato se class.isEnum(), quindi potrebbe funzionare. Ma sembra che il tuo fornitore di persistenza non lo faccia.

+0

Non dice che sia possibile ma non dice che sia impossibile neanche. Dice solo: "Le entità le cui chiavi primarie usano tipi diversi da questi non saranno portatili". In effetti, non dice anche che una classe può essere usata come chiave primaria ma è possibile. – nanda

+0

questa è un'altra cosa, un ID incorporabile. vedere il mio aggiornamento per la parte portabilità. – Bozho

+0

quindi immagino che questa sia una richiesta valida per un miglioramento, non credi? – nanda

4

No, non è possibile utilizzare le enumerazioni come ID perché JPA non permette di definire la propria mappatura per colonne ID (devono essere int o long o qualcosa che JPA in grado di creare con new).

Gli ID non devono essere la chiave aziendale (nel tuo caso: il tipo). L'uso della chiave aziendale come ID è un errore comune nei progetti di DB e dovrebbe essere evitato perché causerà tutti i tipi di problemi in seguito.

Aggiungere una colonna ID indipendente per risolvere il problema.

+0

Sto lavorando con il vecchio database. Potrebbe non essere un buon design ma è lì. L'enum è solo un mucchio di valore rigido. – nanda

0

Vuoi davvero farlo? Questo costrutto non consente di modificare le chiavi enum del database senza aggiornare l'enum nel codice (fail on load), né viceversa (errore di vincolo). Perché non crei solo una tabella AssetType con int pk e name e fai in modo che gli Adkeys abbiano una chiave esterna per AssetType.id come pk?

È possibile caricare AssetTypes dal db all'avvio se è necessario enumerarli nell'app.

+0

Sto lavorando con il vecchio database. Certo che posso cambiarlo ma potrebbe essere problematico. L'enum è solo un mucchio di valore rigido. – nanda