Est-il possible d'utiliser une énumération comme valeur discriminante lors de l'utilisation de la stratégie d'héritage SINGLE_TABLE?Stratégie d'héritage SINGLE_TABLE utilisant des énumérations comme valeur discriminante
Répondre
À ma connaissance, il est impossible avec les annotations:
- valeur discriminante doit être de type
String
- valeur discriminante doit être une compilation constante de temps, à savoir les valeurs de retour des méthodes sur énumérations sont interdit.
yup, lorsque vous définissez discriminateur l'option de l'annotation sont nom et discrimatorType
@DiscriminatorColumn (name="MYDISCRIMINATOR", discriminatorType= DiscriminatorType.INTEGER)
dont DiscriminatorType ne peut être:
DiscriminatorType.STRING
DiscriminatorType.CHAR
DiscriminatorType.INTEGER
malheureux je ne voyais pas hier, mais bien . C'est comme ça
Et notez que 'DiscriminatorType' fait référence au type de base de données et non au type Java. 'DiscriminatorValue' doit toujours avoir un nombre entre guillemets sous forme de chaîne. – TWiStErRob
Non, malheureusement vous ne pouvez pas. Si vous essayez d'utiliser une valeur enum discriminator, vous obtiendrez une exception d'incompatibilité de type ("impossible de convertir MyEnum en String"), car les seuls types de discriminateurs autorisés sont String, Char et Integer. Ensuite, j'ai essayé d'utiliser un nom d'enum et un ordinal combinés avec DiscriminatorType.STRING et DiscriminatorType.INTEGER, respectivement. Mais cela ne fonctionne pas non plus, comme l'annotation @DiscriminatorValue (comme tout autre) nécessite une expression constante:
Cela ne fonctionne pas:
@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
}
ne fonctionne pas non plus:
@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
}
Vous pouvez utiliser DiscriminatorType.INTEGER
et mapper chaque sous-classe avec @DiscriminatorValue("X")
, où X
doit être la valeur ordinale de l'énumération (0,1,2,3 ...).
doit doit être la valeur comme une constante Chaîne. Vous ne pouvez pas utiliser YourEnum.SOME_VALUE.ordinal()
, car les valeurs d'attribut d'annotation doivent être des constantes. Oui, c'est fastidieux. Oui, il est sujet aux erreurs. Mais ça fonctionne.
Il s'agit d'une solution de contournement hacky, mais cela fonctionne, je mettrais des commentaires énormes dans un 'enum' qui est utilisé comme un' DiscriminatorValue'! De même, la même chose fonctionne avec les noms enum (avec 'DiscriminatorType.String' qui peut être plus stable que l'ordinal. – TWiStErRob
Si vous essayez de ne pas dupliquer les valeurs du discriminateur, il existe une solution de contournement simple.
@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";
}
}
Pas super élégant, mais mieux que d'avoir à maintenir les valeurs à plusieurs endroits.
Je voulais juste améliorer la bonne réponse de @asa à propos de la solution de contournement. Habituellement, nous aimons souvent utiliser la colonne discriminante comme un attribut de la classe abstraite, et mappé avec un enum
bien sûr. Nous pouvons toujours utiliser la solution mentionnée ci-dessus et forcer certaines consistances entre enum
noms (utilisés pour mapper la colonne) et String
valeurs (utilisées comme valeurs discriminantes).Voici ma suggestion:
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";
}
}
Et pour les entités, voici le code:
@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 {
…
}
pas encore parfait, mais un peu mieux, je pense.
- 1. LINQ & énumérations comme
- 2. avancée énumérations Java comme dans Ruby
- 3. générer des énumérations aléatoires
- 4. NHibernate: Utilisation d'une colonne discriminante comme relation plusieurs-à-un
- 5. Pourquoi EclipseLink ajoute une colonne discriminante pour la stratégie d'héritage jointe?
- 6. Utilisation des énumérations dans l'API
- 7. énumérations d'emballage en utilisant le compilateur MSVC++
- 8. Importer des énumérations dans GWT
- 9. discriminante basée sur la propriété rejoint
- 10. encapsuler des énumérations ou non?
- 11. Comment implémenter des énumérations COM sécurisées?
- 12. nullables énumérations (??) et LinqToSQL
- 13. JAXB + énumérations + Affichage des valeurs multiples
- 14. Pourquoi est-il mauvais d'utiliser les modèles comme énumérations?
- 15. Passer les énumérations par référence ... la valeur garbage retournée à
- 16. énumérations Databinding à C#
- 17. obtenir une liste des énumérations disponibles
- 18. Énumérations et annotations
- 19. drapeaux énumérations en C#
- 20. Utilisation énumérations
- 21. Java: énumérations anonymes?
- 22. Passer des énumérations à des fonctions en C++
- 23. Où placer des entités commerciales, des énumérations, des exceptions personnalisées?
- 24. Comment faire des énumérations dans Rails 3?
- 25. Java: coulée de type dynamique en utilisant les énumérations
- 26. Boost :: Types aléatoires et énumérations
- 27. Séparation des énumérations de définitions de classe en utilisant des espaces de noms en C++?
- 28. Les énumérations Java sont-elles considérées comme des types primitifs ou de référence?
- 29. Est-il possible de fusionner des énumérations Java (comme Bitwise en C#)?
- 30. en utilisant des instructions de commutation avec des constantes ou des énumérations? (Ce qui est mieux)? C#
JPA 2.1 n'a pas changé cela? –
Ce n'est pas JPA, le langage Java ne vous permet pas d'appeler des méthodes pour les valeurs d'annotation, voir: http://docs.oracle.com/javase/specs/jls/se7/html/jls-9.html#jls-9.7 en 9.7.1, lire la liste: "Le type de' V' est compatible avec l'assignation (§5.2) avec 'T', et de plus:". Donc 'MyEnum.ENUM_CONST.x()' est invalide, 'MyEnum.ENUM_CONST' serait valide, mais' T' est 'String' ici. – TWiStErRob