IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Hibernate Java Discussion :

Comment mapper une colonne de type ENUM ?


Sujet :

Hibernate Java

  1. #1
    Membre régulier Avatar de KneXtasY
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    121
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2004
    Messages : 121
    Points : 109
    Points
    109
    Par défaut Comment mapper une colonne de type ENUM ?
    Bonjour,

    la question se trouve dans l'intitulé du sujet !

    Avez vous un exemple simple ?
    Avec un ENUM('TRUE','FALSE") par exemple ? (oui je sais, Boolean ça existe !)

    Merci d'avance !

  2. #2
    Membre confirmé
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    365
    Détails du profil
    Informations personnelles :
    Localisation : Maroc

    Informations forums :
    Inscription : Janvier 2006
    Messages : 365
    Points : 495
    Points
    495
    Par défaut
    Salut,
    Normalement tu n'as pas grand-chose à faire pour mapper un type Enum, parce que ça fait partie de la spécification Java Persistence, et Hibernate, en tant que provider JPA, l'implémente naturellement. Tout ce que tu as à faire, c'est d'ajouter l'annotation @Enumerated devant ton attribut :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    @Enumerated(EnumType.STRING)
    public MonEnum getAttr1() {
         return attr1;
    }
    Bien évidemment ceci n'est valable que si tu utilises Hibernate Annotations. Dans le cas contraire, il te faudrait créer un "custom UserType" pour mapper ton enum, je crois qu'ils en donnent un exemple dans la doc hibernate, il faut voir.

  3. #3
    Membre régulier Avatar de KneXtasY
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    121
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2004
    Messages : 121
    Points : 109
    Points
    109
    Par défaut
    Citation Envoyé par manblaizo
    Bien évidemment ceci n'est valable que si tu utilises Hibernate Annotations. Dans le cas contraire, il te faudrait créer un "custom UserType" pour mapper ton enum, je crois qu'ils en donnent un exemple dans la doc hibernate, il faut voir.
    Merci pour ta réponse !

    Je n'utilise pas Hibernate Annotations (j'ai des fichiers .hbm).
    Il faut donc que je crée un type spécial pour mapper mon ENUM ?!
    Je vais faire un petit tour sur la documentation officielle.

  4. #4
    Membre chevronné
    Homme Profil pro
    Directeur technique
    Inscrit en
    Janvier 2007
    Messages
    1 348
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Directeur technique

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 348
    Points : 1 787
    Points
    1 787
    Par défaut
    Il me semble que c'est quand même la première chose à faire, avant de poster sur le forum ...
    La section "Persistent enum types" de la doc est des plus claires !

  5. #5
    Membre régulier Avatar de KneXtasY
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    121
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2004
    Messages : 121
    Points : 109
    Points
    109
    Par défaut
    J'utilise Hibernate 3.

    Version finale de la documentation :
    http://www.hibernate.org/hib_docs/v3/reference/fr/html/
    ils ne parlent pas de Persistent enum types !

    Par contre dans les versions précédentes :
    http://www.hibernate.org/hib_docs/re...ing-types-enum
    c'est le cas.

    Mon problème est que je ne trouve pas la classe à implémenter :
    net.sf.hibernate.PersistentEnum
    dans mon cas:
    org.hibernate.???

    J'ai essayé avec Search et Ctrl+Alt+o sous Eclipse, sans résultat !

  6. #6
    Membre confirmé
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    365
    Détails du profil
    Informations personnelles :
    Localisation : Maroc

    Informations forums :
    Inscription : Janvier 2006
    Messages : 365
    Points : 495
    Points
    495
    Par défaut
    Et si tu jettais un coup d'oeil à ceci, ça pourrait t'inspirer :
    http://www.hibernate.org/265.html

  7. #7
    Membre régulier Avatar de KneXtasY
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    121
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2004
    Messages : 121
    Points : 109
    Points
    109
    Par défaut
    Citation Envoyé par manblaizo
    Et si tu jettais un coup d'oeil à ceci, ça pourrait t'inspirer :
    http://www.hibernate.org/265.html
    Merci beaucoup !

  8. #8
    Membre chevronné
    Homme Profil pro
    Directeur technique
    Inscrit en
    Janvier 2007
    Messages
    1 348
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Directeur technique

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 348
    Points : 1 787
    Points
    1 787
    Par défaut
    Citation Envoyé par KneXtasY
    J'utilise Hibernate 3.

    Version finale de la documentation :
    http://www.hibernate.org/hib_docs/v3/reference/fr/html/
    ils ne parlent pas de Persistent enum types !

    Par contre dans les versions précédentes :
    http://www.hibernate.org/hib_docs/re...ing-types-enum
    c'est le cas.

    Mon problème est que je ne trouve pas la classe à implémenter :
    net.sf.hibernate.PersistentEnum
    dans mon cas:
    org.hibernate.???

    J'ai essayé avec Search et Ctrl+Alt+o sous Eclipse, sans résultat !
    Ah oui dsl j'avais parlé un peu vite ...

  9. #9
    Membre régulier Avatar de KneXtasY
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    121
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2004
    Messages : 121
    Points : 109
    Points
    109
    Par défaut
    Citation Envoyé par chtig
    Ah oui dsl j'avais parlé un peu vite ...
    Pas de problème !

    Suite au liens précédant, j'ai suivi l'exemple aprés avoir recopié les classes :
    <property name="sample" type="mypackage.MyEnumUserType" not-null="true"/>
    J'ai bien créer les accesseurs "mypackage.MyEnumUserType" getSample() et setSample() dans la classe mappée.
    Je n'ai pas d'erreur, mon programme se lance correctment.

    Le problème vient du fait que je ne sais pas comment faire pour accéder ou modifier la valeur de ma propriété sample.
    Comment écrire dans le code que la nouvelle valeur est ENUM_B par exemple ?
    En gros, comment faire le liens entre MyEnumUserType et MyEnum ?
    Un genre de MyEnumUserType.setValue(MyEnum.ENUM_B) ...

  10. #10
    Membre confirmé
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    365
    Détails du profil
    Informations personnelles :
    Localisation : Maroc

    Informations forums :
    Inscription : Janvier 2006
    Messages : 365
    Points : 495
    Points
    495
    Par défaut
    Les méthodes getSample()/setSample() doivent se trouver dans ta classe mappée.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    public class Exemple implements Serializable {
          MyEnum sample;
     
          public MyEnum getSample(){
               return sample;
          }
          public void setSample(MyEnum sample) {
              this.sample = sample;
          }
    }
    Et dans le mapping de la classe Exemple tu as :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    <hibernate-mapping>
       <class name="Exemple" ....>
             [...]
             <property name="sample" type="mypackage.MyEnumUserType" not-null="true"/>
           [...]
       </class>
    </hibernate-mapping>
    Et là, tu peux donc affecter les valeurs que tu veux à l'attribut "sample" d'une instance de la classe "Exemple" que tu sauvegarde après dans la base de données. Du genre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    instanceExemple.setSample(MyEnum.ENUM_A);
    Voilà

  11. #11
    Membre régulier Avatar de KneXtasY
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    121
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2004
    Messages : 121
    Points : 109
    Points
    109
    Par défaut
    J'ai bien compris maintenant !

    En fait, j'étais parti comme ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    public class Exemple implements Serializable {
          MyEnumUserType sample;
     
          public MyEnumUserType getSample(){
               return sample;
          }
          public void setSample(MyEnumUserType sample) {
              this.sample = sample;
          }
    }
    Merci beaucoup.

    Mais en fait, je ne sais même pas si ça va fonctionner ...

    "UserType for persisting an Enum with a VARCHAR column"

    Depuis le départ, moi je veux a ENUM column
    Je sais pas trop comment c'est géré dans MySQL.

    J'ai une base existante que je ne peux malheuresement pas modifier ... snif !

    Je vous tiens au courant ...

  12. #12
    Membre confirmé
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    365
    Détails du profil
    Informations personnelles :
    Localisation : Maroc

    Informations forums :
    Inscription : Janvier 2006
    Messages : 365
    Points : 495
    Points
    495
    Par défaut
    Oui, en fait ce qu'il faut bien comprendre c'est que la classe MyEnumUserType que tu crées est celle qui permet de donner des instructions à Hibernate sur comment il doit faire correspondre ton type enum au type sql en base. Pour des attributs de types simples comme int, long, string, hibernate a déjà des classes de mapping par défaut.
    Mais en fait, je ne sais même pas si ça va fonctionner ...
    "UserType for persisting an Enum with a VARCHAR column"
    En gros, ça veut juste dire que ça s'applique quand la propriété "sample" de type Java MyEnum correspond à un champ de type VARCHAR, et pas un INTEGER, par exemple, au niveau de la base de données. Donc en principe, ça doit marcher.

  13. #13
    Membre régulier Avatar de KneXtasY
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    121
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2004
    Messages : 121
    Points : 109
    Points
    109
    Par défaut
    Citation Envoyé par manblaizo
    Oui, en fait ce qu'il faut bien comprendre c'est que la classe MyEnumUserType que tu crées est celle qui permet de donner des instructions à Hibernate sur comment il doit faire correspondre ton type enum au type sql en base. Pour des attributs de types simples comme int, long, string, hibernate a déjà des classes de mapping par défaut.
    Donc quand on met type="string" dans le .hbm, il s'agit d'une classe de mapping d'Hibernate non celle de java (String).

    J'ai fait le test avec l'ENUM, ça fonctionne à merveille !

    Merci beaucoup !

  14. #14
    Membre régulier Avatar de KneXtasY
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    121
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2004
    Messages : 121
    Points : 109
    Points
    109
    Par défaut
    J'ai encore un petit problème ...

    Lorsque je sauvegarde (rends persistant) un objet en base, il n'y a pas de probléme.
    Par contre lorsque j'essaie de récupérer celui ci, j'ai un joli :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    java.lang.NullPointerException
    	at java.lang.Enum.valueOf(Enum.java:187)
    	at EnumUserType.nullSafeGet(EnumUserType.java:33)
    	at org.hibernate.type.CustomType.nullSafeGet(CustomType.java:105)
            ...
    Décidément, j'aurais passé du temps sur ce petit problème ...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
        public Object nullSafeGet(ResultSet resultSet, String[] names, Object owner) throws HibernateException, SQLException { 
            String name = resultSet.getString(names[0]); 
            E result = null; 
            if (!resultSet.wasNull()) { 
                result = Enum.valueOf(clazz, name); 
            } 
            return result; 
        }

  15. #15
    Membre confirmé
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    365
    Détails du profil
    Informations personnelles :
    Localisation : Maroc

    Informations forums :
    Inscription : Janvier 2006
    Messages : 365
    Points : 495
    Points
    495
    Par défaut
    Bonjour,
    J'avoue que ce NullPointerException m'intrigue un peu moi aussi. Quand tu vérifies dans la base de données, tu as bien la valeur sauvegardée ? En tout cas, d'après la trace de l'exception, ce NullPointerException ne devrait avoir que deux causes : soit la valeur récupérée de la base de données est null (ce qui à priori n'est pas le cas), soit l'attribut "clazz" dans la classe EnumUserType est resté à null, auquel cas il faudrait bien vérifier que dans le constructeur de "MyEnumUserType" on a bien super(MyEnum.class) comme c'est spécifié dans le lien indiqué plus haut.
    A part ça, je ne vois plus trop.

  16. #16
    Membre régulier Avatar de KneXtasY
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    121
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2004
    Messages : 121
    Points : 109
    Points
    109
    Par défaut
    Oui en fait clazz était à null ... malgrès le super(MyEnum.class) dans le constructeur de MyEnumUserType !

    Cela venait du fait que j'avais rajouté un constructeur vide sans paramètres ...

    Mais maintenant, j'ai :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    Caused by: org.hibernate.MappingException: Cannot instantiate custom type: EnumUserType
    	at org.hibernate.type.CustomType.<init>(CustomType.java:55)
    	at org.hibernate.type.TypeFactory.heuristicType(TypeFactory.java:245)
    	at org.hibernate.mapping.SimpleValue.getType(SimpleValue.java:260)
    	at org.hibernate.mapping.SimpleValue.isValid(SimpleValue.java:253)
    	at org.hibernate.mapping.Property.isValid(Property.java:185)
            ...



    EDIT : j'ai trouvé, je mettais planté de type dans mon fichier de mapping MyEnumUserType et pas EnumUserType... (C'est pas mon jour ...)

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 4
    Dernier message: 05/10/2009, 18h58
  2. Comment formater une colonne de type charactere ?
    Par NicolaTesla dans le forum Cognos
    Réponses: 4
    Dernier message: 27/05/2009, 18h15
  3. Réponses: 1
    Dernier message: 15/02/2008, 16h55
  4. [VB.Net/Dataview] Comment gérer un filtre sur une colonne de type date ?
    Par silatchom dans le forum Accès aux données
    Réponses: 3
    Dernier message: 07/07/2006, 19h28
  5. Réponses: 5
    Dernier message: 19/04/2005, 09h46

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo