2010-09-03 11 views

Odpowiedz

2

O ile mi wiadomo, nie jest to możliwe z adnotacjami:

  • wartość dyskryminator musi być typu String
  • wartość dyskryminator musi być kompilacji czas na stałym poziomie, czyli wartości zwracane z metod na teksty stałe są nie dozwolony.
+0

JPA 2.1 to się nie zmieniło? –

+0

To nie jest JPA, język Java nie pozwala na wywoływanie metod wartości adnotacji, zobacz: http://docs.oracle.com/javase/specs/jls/se7/html/jls-9.html#jls- 9.7 w 9.7.1, przeczytaj listę: "Typ' V' jest zgodny z przypisaniem (§5.2) z 'T', a ponadto:". Więc 'MyEnum.ENUM_CONST.x()' jest nieprawidłowe, 'MyEnum.ENUM_CONST' będzie poprawne, ale' T' jest tutaj 'String'. – TWiStErRob

2

yup, gdy opcję adnotacji w zdefiniowaniu dyskryminator są nazwa i discrimatorType

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

których DiscriminatorType może być tylko:

DiscriminatorType.STRING 
DiscriminatorType.CHAR 
DiscriminatorType.INTEGER 

niefortunne nie widziałem to wczoraj, ale dobrze . Tak to jest

+3

Należy zauważyć, że "DiscriminatorType" odnosi się do typu DB, a nie do typu Java. Wartość "DiscriminatorValue" musi nadal zawierać liczbę w cudzysłowach jako ciąg. – TWiStErRob

6

Nie, niestety nie możesz.

Jeśli spróbujesz użyć wyliczenia jako wartości dyskryminacyjnej, otrzymasz wyjątek typu niezgodności ("Nie można przekonwertować z MyEnum na ciąg"), ponieważ dozwolone są tylko typy dyskryminatorów: String, Char i Integer. Następnie próbowałem użyć nazwy enum i liczby porządkowej w połączeniu z odpowiednio DiscriminatorType.STRING i DiscriminatorType.INTEGER. Ale to nie działało, jak adnotacji @DiscriminatorValue (jak każdy inny) wymaga stałej ekspresji:

To nie działa:

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

nie działa albo:

@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

Można użyć DiscriminatorType.INTEGER i mapować każdą podklasę za pomocą @DiscriminatorValue("X"), gdzie X musi być wartością porządkową wyliczenia (0,1,2,3 ...).

To musi być być wartością jako ciąg stały. Nie można użyć wartości YourEnum.SOME_VALUE.ordinal(), ponieważ wartości atrybutów adnotacji muszą być stałe. Tak, to jest żmudne. Tak, jest podatny na błędy. Ale działa.

+0

To jest hacky, ale działa, będę umieścić ogromne komentarze w 'enum', który jest używany jako" DiscriminatorValue "! To samo działa z nazwami enum (z 'DiscriminatorType.String', które mogą być bardziej stabilne niż porządkowe. – TWiStErRob

23

Jeśli próbujesz osiągnąć to, aby nie powielać wartości dyskryminatora, istnieje proste obejście tego problemu.

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

Niezwykle elegancki, ale lepszy niż konieczność zachowania wartości w wielu miejscach.

13

Po prostu chciałem poprawić doskonałą odpowiedź @asa na temat obejścia tego problemu. Zwykle często lubimy używać kolumny dyskryminacyjnej jako atrybutu klasy abstrakcyjnej i oczywiście mapujemy ją na enum. Nadal możemy korzystać z wyżej wspomnianego rozwiązania i wymuszać pewne zgodności między nazwami enum (używanymi do odwzorowania kolumny) i wartościami String (używanymi jako wartości dyskretatora).Oto moja propozycja:

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

I dla podmiotów, oto kod:

@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 { 
    … 
} 

Wciąż nie jest doskonały, ale trochę lepiej, myślę.

Powiązane problemy