2010-09-15 14 views
5

Usando JPA, ¿podemos definir una enumeración como identificación de una entidad?Usando enum como id

He intentado lo siguiente:

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

} 

Usando OpenJPA, se queja:

org.apache.openjpa.persistence.ArgumentException: La clase id "aa.AssetType clase" especifica por tipo "clase aa.Adkeys" no tiene un constructor público no-args.

Así que mis preguntas son:

  • deberíamos poder utilizar enumeración como ID para una entidad en la APP? (es decir, hay un error en OpenJPA)
  • o me equivoco?
  • y hay alguna solución para tal problema?
+0

@Nathan: Entonces tiene que ser un error. –

Respuesta

7

La especificación JPA no dice que esto es posible:

2.1.4 claves primarias y Entidad Identidad

La clave principal (o campo o propiedad de una clave primaria compuesta) debe ser uno de los siguientes tipos: cualquier tipo de primitiva Java; cualquier tipo de envoltura primitiva; java.lang.String; java.util.Date; java.sql.Date. Sin embargo, en general, los tipos numéricos aproximados (p. Ej., Los tipos de coma flotante) nunca se deben usar en las claves principales. Las entidades cuyas claves principales usan tipos distintos a estos no serán portátiles.

Si realmente quiere tener un tiempo de compilación número de registros fija para una entidad determinada, puede utilizar una clave principal String o int y asignarle AssetType.FOO.name() o AssetType.FOO.ordinal()

Y no portátiles aquí medios que algún proveedor de persistencia puede admitir otras cosas, pero puede no funcionar para otro proveedor. Al igual que con la enumeración: si el proveedor de persistencia tiene soporte especial para eso, eso no intenta crear una instancia, sino que lo procesa especialmente después de comprobar si class.isEnum(), entonces podría funcionar. Pero parece que su proveedor de persistencia no hace esto.

+0

No dice que esto sea posible, pero tampoco dice que sea imposible. Simplemente dice: 'Las entidades cuyas claves principales usan tipos distintos de estos no serán portátiles'. De hecho, tampoco dice que una clase se puede usar como clave principal, pero es posible. – nanda

+0

eso es otra cosa: una identificación incrustable. ver mi actualización para la parte de portabilidad. – Bozho

+0

así que supongo que esta es una solicitud válida para una mejora, ¿no crees? – nanda

4

No, no se puede utilizar como enumeraciones identificación porque la APP no permite definir su propio mapeo de columnas ID (deben ser int o long o algo que la APP puede crear con new).

Los ID no deben ser la clave comercial (en su caso: el tipo). El uso de la clave comercial como ID es un error común en los diseños de BD y debe evitarse porque causará todo tipo de problemas más adelante.

Agregue una columna de ID independiente para resolver el problema.

+0

Estoy trabajando con una base de datos anterior. Puede que no sea un buen diseño, pero está ahí. La enumeración es solo un montón de valor rígido. – nanda

0

¿De verdad quieres hacer esto? Esta construcción no permite cambiar las claves enum de la base de datos sin actualizar la enumeración en el código (error en la carga), ni al revés (falla de la restricción). ¿Por qué no simplemente creas una tabla AssetType con int pk y name, y haces que los Adkeys tengan una clave foránea para AssetType.id como pk?

Puede cargar AssetTypes desde el db al inicio si necesita enumerarlos en su aplicación.

+0

Estoy trabajando con una base de datos antigua. Por supuesto que puedo cambiarlo, pero podría ser problemático. La enumeración es solo un montón de valor rígido. – nanda