2010-09-04 13 views
2

Je fais une simple page web et j'ai une entité NurseForm. Lorsque l'infirmière voit un patient, elle remplit ce formulaire.Hibernate Mapping: Classe ayant plus d'une valeur possible d'une énumération

Une de ce champ de formulaire est « Actions fait » qui est essentiellement un ENUM avec:

public enum NurseAction { 
    GIVE_MEDICINE, PERFORM_SUTURE, SPRAY_THERAPY, NEBULIZATIONS; 
} 

Une infirmière peut effectuer plus d'une action si j'ai une propriété:

private Collection<NurseAction> nurseActions; 

De ce que je comprends, j'ai besoin de NurseAction pour être une entité, mais si je le fais, je devrais remplir le DB à la main. Puis-je éviter cela? Quelle est la meilleure façon de résoudre cela? PS: Je suis un débutant complet à Hibernate.

Répondre

2

Vous pouvez essayer d'utiliser @CollectionOfElements(targetElement=NurseAction.class) (vous pouvez essayer d'omettre l'attribut et laisser ASSUMER Veille prolongée, il repose sur le paramètre de type de la collection)

Notez que cette annotation est dépréciée en veille prolongée 3.5, en faveur de la même annotation de JPA 2.0.

+0

cool. J'ai ajouté '@CollectionOfElements (targetElement = NurseAction.class)' à mon getter 'NurseForm' et j'enlève le '@ Entity' de l'énumération. Il construit avec succès, mais je ne comprends pas comment Hibernate va le mapper. Pouvez-vous expliquer cela? – Macarse

+0

Je ne sais pas, essayez-le, avec 'hbm2ddl.auto = true'. il peut s'agir d'un 'nom()' ou d'un ordinal() 'séparé par des virgules, ou d'une nouvelle table les créant. – Bozho

+0

Le remplacement est '@ ElementCollection'. – whiskeysierra

1

Malheureusement, Hibernate ne supporte pas (encore) les collections d'Enums correctement. Mais ne pensez-vous pas que de nouvelles actions seront probablement ajoutées plus tard? Je recommanderais d'utiliser une Entité pour l'action afin de vous assurer que vous n'avez pas à redéployer votre application entière simplement parce que vous ajoutez une action ...

Bien sûr, vous pouvez toujours faire quelque chose (moche) :) comme ceci:

@Entity public class NurseForm { 
    private String actions; 

    public void setActions(final List<NurseAction> actions) { 
    if(actions == null) 
     this.actions = null; 
    else 
     this.actions = Joiner.on(',').join(actions); 
    } 

    public List<NurseAction> getActions() { 
     List<NurseAction> returner = Lists.newArrayList(); 
     if(this.actions != null) { 
     Iterable<String> actions = Splitter.on(',').split(this.actions); 
     for(String action : actions) 
      returner.add(NurseAction.valueOf(action); 
     } 
     return returner; 
    } 
} 

Clause de non-responsabilité: tout ceci n'a pas été testé et n'a même pas été compilé. En outre, je fais un usage intensif de Google Goyave parce que je l'aime. :)

Bonne chance!

+0

Je préférerais renvoyer une vue en direct au lieu d'un snapshot dans' getActions' qui écrit les changements dans le champ privé immédiatement. Il n'y aurait pas besoin d'un setter. – whiskeysierra

+0

Une autre idée serait d'utiliser une méthode '@ PreUpdate' (et' @ PrePersist?) Qui sérialise la valeur actuelle d'un champ transitoire contenant la collection dans un champ mappé contenant la valeur sérialisée. – whiskeysierra

+1

Pourquoi dites-vous que ce n'est pas pris en charge? Qu'en est-il de '@ CollectionOfElements' dans pré 3.5? –

1

En supposant que toute action ne peut être appliquée qu'une seule fois à un patient, je suggère d'utiliser Set au lieu de Collection. Veuillez me corriger si cela ne correspond pas à vos besoins. Dans le cas où la sémantique est définie, je suggère d'utiliser un EnumSet pour stocker les actions. C'est extrêmement rapide et conforme à l'implémentation Set. Il utilise une seule valeur long sous le capot (tant que vous avez moins de 64 actions).

Maintenant, ma solution serait de stocker une colonne de numéro unique à la base de données en utilisant UserType personnalisé qui mappe de EnumSet à long et vice versa.

Pros

  • seule colonne
  • rapide
  • très petite surcharge

Contre

  • valeurs dans la base de données sont difficiles à lire (par les humains)
  • requêtes personnalisées sont difficiles

Si vous voulez jeter un oeil à une mise en œuvre réutilisable générique et abstraite d'un tel UserType, jetez un oeil à http://source.palava2.org/browse/commons.svn.cosmocode.de/cosmocode-hibernate/trunk/src/main/java/de/cosmocode/hibernate/EnumSetUserType.java?r=HEAD