2010-09-03 10 views

risposta

2

A mia conoscenza, questo non è possibile con le annotazioni:

  • valore discriminatore deve essere di tipo String
  • valore discriminatore deve essere una fase di compilazione costante, ossia valori restituiti da metodi su enums sono non autorizzato.
+0

JPA 2.1 non ha cambiato questo? –

+0

Non è JPA, il linguaggio Java non consente di chiamare metodi per i valori di annotazione, vedere: http://docs.oracle.com/javase/specs/jls/se7/html/jls-9.html#jls-9.7 alla 9.7.1, leggi la lista: "Il tipo di' V' è compatibile con l'assegnazione (§5.2) con 'T', e inoltre:". Quindi 'MyEnum.ENUM_CONST.x()' non è valido, 'MyEnum.ENUM_CONST' sarebbe valido, ma' T' è 'String' qui. – TWiStErRob

2

Yup, quando si definisce discriminatore scelta del annotazioni sono nome e discrimatorType

@DiscriminatorColumn (name="MYDISCRIMINATOR", discriminatorType= DiscriminatorType.INTEGER) 

di cui DiscriminatorType possono essere solo:

DiscriminatorType.STRING 
DiscriminatorType.CHAR 
DiscriminatorType.INTEGER 

sfortunato non ho visto ieri, ma ben . Questo è il modo in cui è

+3

E si noti che 'DiscriminatorType' fa riferimento al tipo di DB e non al tipo Java. 'DiscriminatorValue' deve avere ancora un numero tra virgolette come stringa. – TWiStErRob

6

No, purtroppo non è possibile.

Se si tenta di utilizzare un valore enumeratore come discriminatore, si otterrà un'eccezione di tipo Mancata corrispondenza ("non può convertire da MyEnum in stringa"), poiché gli unici tipi di discriminatore consentiti sono String, Char e Integer. Successivamente, ho provato ad usare il nome e l'ordinale di enum in combinazione con DiscriminatorType.STRING e DiscriminatorType.INTEGER, rispettivamente. Ma questo non ha funzionato o, come l'annotazione @DiscriminatorValue (come qualsiasi altro) richiede un'espressione costante:

Questo non funziona:

@Entity 
@Inheritance(strategy=InheritanceType.SINGLE_TABLE) 
@DiscriminatorColumn(name="FREQUENCY", 
    discriminatorType=DiscriminatorType.STRING 
)  
public abstract class Event {} 

@Entity 
@DiscriminatorValue(value=Frequency.WEEKLY.name()) 
public class WeeklyEvent extends Event { 
    // Exception: The value for annotation attribute DiscriminatorValue.value must be a constant expression 
} 

non funziona neanche:

@Entity 
@Inheritance(strategy=InheritanceType.SINGLE_TABLE) 
@DiscriminatorColumn(name="FREQUENCY", 
    discriminatorType=DiscriminatorType.INTEGER 
) 
public abstract class Event {} 

@Entity 
@DiscriminatorValue(value=Frequency.WEEKLY.ordinal()) 
public class WeeklyEvent extends Event { 
    // Exception: The value for annotation attribute DiscriminatorValue.value must be a constant expression 
} 
1

È possibile utilizzare DiscriminatorType.INTEGER e mappare ciascuna sottoclasse con @DiscriminatorValue("X"), dove X deve essere il valore ordinale dell'enumerazione (0,1,2,3 ...).

È deve essere il valore come una stringa costante. Non è possibile utilizzare YourEnum.SOME_VALUE.ordinal(), perché i valori degli attributi di annotazione devono essere costanti. Sì, è noioso. Sì, è soggetto a errori. Ma funziona.

+0

Questa è una soluzione hacky, tuttavia funziona, inserisco enormi commenti in un 'enum' che viene usato come' DiscriminatorValue'! Anche lo stesso funziona con i nomi enum (con 'DiscriminatorType.String' che potrebbe essere più stabile dell'ordinale. – TWiStErRob

23

Se quello che stai cercando di ottenere è di non duplicare i valori del discriminatore, c'è una soluzione semplice.

@Entity 
@Inheritance(strategy=InheritanceType.SINGLE_TABLE) 
@DiscriminatorColumn(name="FREQUENCY", 
    discriminatorType=DiscriminatorType.STRING 
)  
public abstract class Event { 
} 

@Entity 
@DiscriminatorValue(value=Frequency.Values.WEEKLY) 
public class WeeklyEvent extends Event { 
    … 
} 

public enum Frequency { 
    DAILY(Values.DAILY), 
    WEEKLY(Values.WEEKLY), 
    MONTHLY(Values.MONTHLY); 

    private String value; 

    … 

    public static class Values { 
     public static final String DAILY = "D"; 
     public static final String WEEKLY = "W"; 
     public static final String MONTHLY = "M"; 
    } 
} 

Non super elegante, ma meglio che dover mantenere i valori in più posizioni.

13

Volevo solo migliorare l'ottima risposta di @asa alla soluzione alternativa. Solitamente, spesso ci piace utilizzare la colonna discriminator come attributo della classe astratta e ovviamente mappata con uno enum. Possiamo ancora usare la soluzione menzionata sopra e forzare alcune consistenze tra i nomi enum (usati per mappare la colonna) e i valori String (usati come valori del discrimnator).Qui è il mio suggerimento:

public enum ELanguage { 
    JAVA(Values.JAVA), GROOVY(Values.GROOVY); 

    private ELanguage (String val) { 
    // force equality between name of enum instance, and value of constant 
    if (!this.name().equals(val)) 
     throw new IllegalArgumentException("Incorrect use of ELanguage"); 
    } 

    public static class Values { 
    public static final String JAVA= "JAVA"; 
    public static final String GROOVY= "GROOVY"; 
    } 
} 

E per le entità, ecco il codice:

@Entity 
@Inheritance(strategy=InheritanceType.SINGLE_TABLE) 
@DiscriminatorColumn(name="LANGUAGE_TYPE", discriminatorType=DiscriminatorType.STRING)  
public abstract class Snippet { 
    // update/insert is managed by discriminator mechanics 
    @Column(name = "LANGUAGE_TYPE", nullable = false, insertable = false, updatable = false) 
    @Enumerated(EnumType.STRING) 
    public ELanguage languageType 
} 

@Entity 
@DiscriminatorValue(value=ELanguage.Values.JAVA) 
public class JavaSnippet extends Snippet { 
    … 
} 

Ancora non non è perfetto, ma un po 'meglio, credo.

Problemi correlati