2009-10-20 7 views
16

Je dois mapper les énumérations qui n'ont pas implémenté l'interface auparavant à la base de données existante, qui stocke des énumérations dans la même table que la classe propriétaire en utilisant le @Enumerated(EnumType.STRING).Mappage enum Hibernate

class A { 
    HasName name; 
} 

interface HasName { 
    String getName(); 
} 

enum X implements HasName { 
    John, Mary; 

    public String getName() { return this.name(); } 
} 

enum Y implements HasName { 
    Tom, Ann; 

    public String getName() { return this.name(); } 
} 

Comment le mappage devrait être géré dans ce cas? La persistance dans la base de données ne change pas car toutes les énumérations implémentant l'interface auront des valeurs différentes, mais je ne suis pas sûr de la manière dont les objets doivent être récupérés depuis la base de données (ai-je besoin d'un mappeur personnalisé enum utilisant les classes enum spécifiées? Hibernate supporte-t-il nativement cette fonctionnalité?).

Répondre

7

Il est possible de créer une coutume UserType (par exemple this one) et de l'utiliser à partir de vos applications

<property name="type" not-null="true"> 
    <type name="at.molindo.util.hibernate.EnumUserType"> 
    <param name="enumClass"> 
     com.example.MyEnum 
    </param> 
    </type> 
</property> 

EDIT: Mise en veille prolongée est livré avec son propre EnumType (depuis 3.2 hibernate-annotations, depuis 3.6 Mise en veille prolongée-core - ne savait pas qu'il était en hibernation-annotations au moment de l'écriture, mais voir Diego's answer). Hibernate fournit org.hibernate.type.EnumType pour mapper les types énumérés.

+0

Dans mon cas, je ne sais pas ce que la classe de l'ENUM sera. Lors de l'instanciation de 'A', Hibernate devra choisir l'une des énumérations {X, Y}. – dm3

+0

Il ne devrait pas être difficile de modifier l'exemple de l'implémentation UserType selon vos besoins. Par exemple, au lieu de stocker uniquement la valeur, vous pouvez également stocker la classe (par exemple com.example.X.John ou X.John, mais vous aurez besoin d'un mappage de X à com.example.X) – sfussenegger

+0

Signifie besoin d'un mappeur personnalisé (n'a pas vu votre lien vers pastebin). Merci d'avoir répondu. – dm3

50

Par exemple,

package com.igalia.enumerates; 

public enum Status { 
    BUSY, 
    AVAILABLE; 
} 

package com.igalia.entities; 

class MyClass { 
    private Status status; 
} 

Ensuite, faites votre mapping Hibernate comme suit:

<class name="MyClass"> 
    <id name="id"> 
     <generator class="native"/> 
    </id> 

    <property name="status"> 
     <type name="org.hibernate.type.EnumType"> 
     <param name="enumClass">com.igalia.enumerates.Status</param> 
     </type> 
    </property> 
</class> 

Et voilà. Si vous préférez utiliser les annotations JPA au lieu de hbm.xml, utilisez @Enumerated (EnumType.STRING). Vérifiez ici:

Enumerations in Hibernate

+0

Comment définissez-vous une valeur par défaut pour cela? J'ai ajouté l'élément suivant à mais cela n'a pas fonctionné pour moi: Timo

+1

@valmar vous pouvez initialiser * status * au niveau de la classe (ou le faire dans son constructeur). Par exemple, 'statut d'état privé = statut.BUSY;' –

Questions connexes