2010-02-24 6 views
1

je un utilisateur de tableMapping deux tables 0..n dans Hibernate


CREATE TABLE "USERS" (
    "ID" NUMBER NOT NULL , 
    "LOGINNAME" VARCHAR2 (150) NOT NULL) 

et j'ai un deuxième SpecialUtilisateurs de table. Aucun UserId ne peut apparaître deux fois dans la table SpecialUsers et seul un petit sous-ensemble des ID des utilisateurs dans la table Users est contenu dans la table SpecialUsers.


CREATE TABLE "SPECIALUSERS" (
    "USERID" NUMBER NOT NULL, 
CONSTRAINT "PK_SPECIALUSERS" PRIMARY KEY ("USERID")) 

ALTER TABLE "SPECIALUSERS" ADD CONSTRAINT "FK_SPECIALUSERS_USERID" FOREIGN KEY ("USERID") 
REFERENCES "USERS" ("ID") 
/

Cartographie de la table des utilisateurs dans Hibernate fonctionne ok


<hibernate-mapping package="com.initech.domain"> 
    <class name="com.initech.User" table="USERS"> 

     <id name="id" column="ID" type="java.lang.Long"> 
      <meta attribute="use-in-tostring">true</meta> 
      <generator class="sequence"> 
       <param name="sequence">SEQ_USERS_ID</param> 
      </generator> 
     </id> 

     <property name="loginName" column="LOGINNAME" type="java.lang.String" not-null="true"> 
      <meta attribute="use-in-tostring">true</meta> 
     </property> 

    </class> 
</hibernate-mapping> 

Mais je me bats pour créer le mappage de la table SpecialUtilisateurs. Tous les exemples (par exemple dans la documentation d'Hibernate) dans Internet que je trouve n'ont pas ce type d'auto-référence. J'ai essayé une application comme ceci:


<hibernate-mapping package="com.initech.domain"> 
    <class name="com.initech.User" table="SPECIALUSERS">   

     <id name="id" column="USERID"> 
      <meta attribute="use-in-tostring">true</meta> 
      <generator class="foreign"> 
       <param name="property">user</param> 
      </generator> 
     </id> 

     <one-to-one name="user" class="User"/> 

    </class> 
</hibernate-mapping> 

mais obtenu l'erreur


Invocation of init method failed; nested exception is org.hibernate.DuplicateMappingException: 
Duplicate class/entity mapping com.initech.User

Comment dois-je la carte la table SpecialUtilisateurs? Ce dont j'ai besoin au niveau de l'application est une liste des objets Utilisateur contenus dans la table SpecialUsers.

+0

Pourquoi ne pas simplement ajouter un champ 'spécial' à la table USERS? –

+0

J'ai considéré cela, mais étant donné qu'il y a très peu d'utilisateurs "spéciaux" (actuellement un) et de très nombreux utilisateurs, cela ne semblait pas correct. À long terme, cela rendrait également la table Users peu claire si chaque petite propriété, qui ne s'applique qu'à un petit sous-ensemble d'utilisateurs, serait ajoutée directement à la table Users. Une autre raison est également que si les utilisateurs "spéciaux" ont plus d'attributs liés à leur "particularité" à l'avenir, il est facile d'étendre la table SpecialUsers. – simon

+0

pourquoi pensez-vous qu'il existe une relation 0..n quelque part? Votre modèle physique ne reflète pas cela, il représente une hiérarchie parent-enfant pure (c'est-à-dire l'héritage). Est-ce que je manque quelque chose? –

Répondre

2

Comment mapper la table SpecialUsers?

Selon la structure de vos USERS et SPECIALUSERS tables, vous avez une hiérarchie Table per subclass et il est parfaitement possible de cartographier ce genre de hiérarchie avec Hibernate.

Tout d'abord, assurez-vous que SpecialUserhérite de User au niveau du modèle d'objet (ce qui est une relation d'héritage, pas une auto-référence).

public class SpecialUser extends User { 
} 

Ensuite, déclare un élément <joined-subclass> dans la cartographie du User:

<hibernate-mapping package="com.initech.domain"> 
    <class name="com.initech.User" table="USERS"> 

     <id name="id" column="ID" type="java.lang.Long"> 
      <meta attribute="use-in-tostring">true</meta> 
      <generator class="sequence"> 
       <param name="sequence">SEQ_USERS_ID</param> 
      </generator> 
     </id> 

     <property name="loginName" column="LOGINNAME" type="java.lang.String" not-null="true"> 
      <meta attribute="use-in-tostring">true</meta> 
     </property> 

     <joined-subclass name="com.initech.SpecialUser" table="SPECIALUSERS"> 
      <key column="USERID"/> 
     </joined-subclass> 

    </class> 
</hibernate-mapping> 

Ce que je dois au niveau de l'application est une liste des objets utilisateur contenus dans la table SpecialUtilisateurs.

La requête HQL suivante retournera tous les SpecialUser (qui sont User aussi):

from SpecialUser 

Si plus tard, vous devez ajouter des colonnes à la table SPECIALUSERS, ajoutez les attributs à la classe SpecialUser correspondants et les mapper à l'intérieur de l'élément <joined-subclass>. Reportez-vous au lien fourni (à la documentation) pour les détails.

1

Si vous devez vraiment utiliser une seconde table, vous devez la mapper à une nouvelle classe. Hibernate peut toujours uniquement mapper une table à une classe.

Vous pouvez également ajouter une colonne à la table utilisateur indiquant "Cet utilisateur est spécial". Si ce n'est pas une option, créez une vue qui joint les deux tables et simule ainsi cette colonne. Ensuite, vous pouvez sélectionner les utilisateurs par cette colonne.

Si vous adoptez la méthode des deux classes, vous devez charger une liste des utilisateurs spéciaux et effectuer le mappage dans votre application.

[EDIT] Vous devriez peut-être examiner les relations parents-enfants. Dans votre cas, l'utilisateur est le parent et ses rôles sont les enfants. Ainsi, chaque utilisateur a des rôles 0..n qui sont mappés dans une table différente. Vous pouvez ensuite utiliser cette HQL

from User u where :role in elements(u.roles) 

pour trouver tous les utilisateurs avec un certain rôle. Mais la plupart du temps, vous aurez un utilisateur spécifique et aurez juste besoin de demander si elle a un certain rôle.

+0

Merci, le point sur les rôles est perspicace. – simon

+0

Aaroon, alors que le titre initial de la question était assez confus, je ne pense pas que votre édition reflète l'intention initiale (il correspond à votre réponse, mais ce n'est pas ce que le PO demandait pour mon humble avis). Et le modèle physique ne représente pas une relation 0..n BTW, c'est une relation d'héritage pure. –

Questions connexes