2009-02-03 3 views
2

Hello Stack Overflow experts, j'ai besoin de votre expertice:One-To-Many unidirectionnelles sur un DB existant

Je suis en train d'utiliser Hibernate sur une base de données existant. J'essaie actuellement de charger un objet Utilisateur et une liste d'objets UserData qui vont avec.

dans la base de données la mise en page (simplifié) est

| User  |  |   UserData    | 
----------------  ----------------------------------- 
uid | username |  | uid | parentuid | field | value | 

Ainsi, chaque objet utilisateur correspond à tous les objets UserData où UserData.parentuid = User.uid.

Mon utilisateur fichier de mappage de classe

<class name="com.agetor.commons.security.User" table="ac_users"> 
    <id name="uid" column="uid" type="long" > 
     <!--<generator class="native"/>--> 
    </id> 
    <property name="username" column="username" /> 

    <list name="fieldData" cascade="all"> 
     <key column="parentuid" not-null="true" /> 
     <index column="parentuid" /> 
     <one-to-many class="com.agetor.commons.fields.FieldData"/> 
    </list> 

</class> 

fichier de mappage Mu UserData

<class name="com.agetor.commons.fields.FieldData" table="ac_userdef_data"> 
    <id name="uid" column="uid" type="long" > 
    <!--<generator class="native"/> --> 
    </id> 
    <!--<property name="parentuid" column="parentuid" /> --> 
    <property name="fieldname" column="fieldname" /> 
    <property name="value" column="value" /> 
</class> 

Jusqu'à présent, je l'ai essayé beaucoup de différentes configurations et tous ont eu des degrés divers de failue. Le code collé ici ne fonctionne pas.

  • La propriété parentuid est mise en commentaire, car Hibernate renvoie une erreur «Colonne répétée dans le mappage».
  • Actuellement, il reste une « colonne répétée dans la cartographie » sur le champ uid, j'utiliser pour <list-index />
  • Je ne comprends pas où je précise que UserData.parentuid est la clé étrangère et que la liste doit utiliser User.uid comme clé.

J'espère que quelqu'un est en mesure d'aider.


Lorsque vous définissez à la fois un One-To-Many et Many-to-One, ce ne rend pas bi-directionnel? Le modèle de travail actuel est unidirectionnel et UserData ne fait pas référence à l'utilisateur. Votre suggestion échoue, car Hibernate n'a pas pu trouver une méthode get ou set pour User sur UserData.

est-il implicite que ce code utilise User.uid comme clé et correspond à cette contre la colonne UserData.parentuid? Ou ce fait est-il spécifié ailleurs? Je suis toujours en train d'apprendre Hibernate et de travailler mon chemin à travers la documentation et les exemples que je peux trouver.

Répondre

0

Ceci est la dernière version mise à jour pour ce problème Cette configuration peut être chargée avec succès à partir de la base de données L'enregistrement ne fonctionne pas J'ai décidé de modifier la conception de base de données au lieu, l'affichage si im ici pour cette référence pour les autres, avant de renoncer à cette approche

<class name="com.agetor.commons.security.User" table="ac_users"> 
    <id name="uid" column="uid" type="long" > 
     <generator class="increment"/> 
    </id> 
    <property name="deleted" column="deleted" /> 
    <property name="username" column="username" /> 
    <property name="password" column="passwd" /> 
    <property name="disabled" column="disabled" /> 
    <property name="lockout" column="lockout" /> 
    <property name="expires" column="expires" /> 
    <bag name="fieldData" lazy="extra"> 
     <key column="parentuid" not-null="true" /> 
     <one-to-many class="com.agetor.commons.fields.FieldData"/> 
    </bag> 
    <bag name="groups" table="ac_group_rel" access="field" lazy="extra"> 
     <key column="useruid"/>   
     <many-to-many column="groupuid" class="com.agetor.commons.security.Group"/> 
    </bag>   
    <join table="ac_userdef_data" optional="true" fetch="join"> 
     <subselect> 
      select 
       * 
      from 
       ac_userdef_data data 
      where 
       data.objectname = 'user' and 
       data.fieldname = 'firstname' 
     </subselect> 
     <key column="parentuid" /> 
     <property name="firstname" formula="(select data.value from ac_userdef_data data where data.fieldname = 'firstname' and data.uid = uid)"/> 
    </join> 
    <join table="ac_userdef_data" optional="true" fetch="join"> 
     <subselect> 
      select 
       * 
      from 
       ac_userdef_data data 
      where 
       data.objectname = 'user' and 
       data.fieldname = 'lastname' 
     </subselect>   
     <key column="parentuid" /> 
     <property name="lastname" formula="(select data.value from ac_userdef_data data where data.fieldname = 'lastname' and data.uid = uid)"/> 
    </join> 

</class> 
0

Essayez cette (drycode):

<class name="com.agetor.commons.security.User" table="ac_users"> 
    <id name="uid" column="uid" type="long" > 
    <!--<generator class="native"/>--> 
    </id> 
    <property name="username" column="username" /> 

    <list name="fieldData" inverse="true"> 
    <key column="parentuid" not-null="true" /> 
    <one-to-many class="com.agetor.commons.fields.FieldData"/> 
    </list> 
</class> 

<class name="com.agetor.commons.fields.FieldData" table="ac_userdef_data"> 
    <id name="uid" column="uid" type="long" > 
    <!--<generator class="native"/> --> 
    </id> 
    <many-to-one name="user" class="com.agetor.commons.security.User" fetch="join"> 
    <column name="parentuid" not-null="true"/> 
    </many-to-one> 
    <property name="fieldname" column="fieldname" /> 
    <property name="value" column="value" /> 
</class> 

Si cela fonctionne, essayez d'ajouter la substance d'index et cascade que je me suis permis.

acclamations,
mitch

0

Je pense que vous êtes proche, mais la liste est probablement pas la structure de données que vous voulez dans votre nouvelle classe utilisateur. Une liste implique un classement des éléments enfants, que les tables ne semblent pas avoir. Si vous avez une collection indexée comme une liste, les données doivent avoir une colonne séparée qui fournit l'index, d'où le problème "Colonne répétée dans le mappage".

Les règles empiriques que j'utilise sont les suivantes: chaque mappage doit inclure une entrée pour chaque membre de la classe à mapper. Ainsi, par exemple, votre classe User doit avoir une entrée pour sa collection de FieldData, mais votre mappage FieldData n'a pas besoin d'une entrée pour parentuid, puisque cette colonne ne correspond pas à un élément de la classe FieldData - elle est simplement utilisée pour mettre FieldData dans la collection de l'objet parent.

Si l'objet Utilisateur contient réellement une collection ordonnée de FieldData, utilisez un ensemble à la place. D'un autre côté, je pense qu'il est plus probable que vous vouliez une carte de FieldData à la place, en utilisant le nom 'field' comme index. Ensuite, la classe FieldData n'a pas besoin de mapper la colonne 'field' et ne l'aura pas en tant que membre, elle aura juste la valeur (et tous les autres champs de cette table - bien sûr s'il n'y a qu'une seule colonne à gauche de la carte, vous pouvez vous retrouver avec une carte de chaînes à chaînes

0

-.>

<list name="fieldData" cascade="all"> 
    <key column="uid" not-null="true" /> 
    <index column="parentuid" /> 
    <one-to-many class="com.agetor.commons.fields.FieldData"/> 
</list> 

Essayez, je viens de changer coloumn clé comme parentuid uid. (Et mieux utilisation définies dans les correspondances de mise en veille prolongée)

acclamations, Prasad .. Nagendra

Questions connexes