web-dev-qa-db-fra.com

mise en veille prolongée de deux tables par entité

J'ai une entité - User. Il est décrit par User.class.

Hibernate crée une table par entité, donc lorsque j'appelle session.save(user), mes données sont toujours enregistrées dans cette table.

Maintenant, j'ai besoin d'une autre table pour les données du même type User, et je dois enregistrer mon entité dans cette table uniquement.

Structure de données (quelque chose comme ça):

table users_1_table{
  string id;
  string username;
}

table users_2_table{
  string id;
  string username;
}

travaillez avec ceci:

session.save(user1,"users_1_table")
session.save(user2,"users_2_table")

et en conséquence je devrais avoir user1 dans users_1_table et user2 dans users_2_table.

En raison de la limitation du système, je ne peux pas mettre ces deux objets dans une même table. (Même la création d'un champ supplémentaire est une mauvaise idée).

Puis-je le faire sans sous-classement? Vous utilisez la configuration de mise en veille prolongée par programme?

17
msangel

Préface:

C'est une question largement posée même sur SO, et aussi largement les réponses sont liées à l'approche Subclass ou en fait SuperClass (par exemple [ 1 ])

Réponse réelle:

Sur ces messages [ 2 ], [], ils suggèrent d'utiliser un mappage xml avec le paramètre EntityName.

Donc, en mappant avec xml, vous n'avez pas besoin de superclasse, donnez simplement le paramètre EntityName à deux mappages identiques.

Exemple de mappage:

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
   <class name="DomainModel.User, DomainModel"
     table="User1Object" entity-name="User1Object">  
         <id name="_id" access="field" column="id">
             <generator class="assigned"/>
         </id>
        <property name= ...>
 </class>
 <class name="DomainModel.User, DomainModel"
     table="User2Object" entity-name="User2Object">
         <id name="_id" access="field" column="id">
            <generator class="assigned"/>
         </id>
        <property name= ...>
</class>
</hibernate-mapping>

Ensuite, selon le type d'entité dont vous avez besoin, vous appelez les méthodes de session appropriées en tant que:

_session.Save("User1Object", user1)

ou

_session.Save("User2Object", user2)

Les messages 2 et 3 ont été utilisés comme base pour cet extrait. Source officielle [ 4 ]

Après le match:

Une réponse à la première question qui est en fait un lien vers cet article [ 5 ] il existe une approche différente:

Vous dites au revoir à la première instance de l'objet, clonez les données vers une nouvelle instance et persistez avec un nom différent. Ainsi, aucune violation sur la logique Hibernate et le contenu de tout le monde: mêmes données sur deux tables et aucune sous-classe utilisée.

Eh bien, l'implémentation ou le code ou la crédibilité de cette approche est tel ou tel, je ne l'ai pas testé non plus.

Un autre cas:

Dans cet article [ 6 ] il y a une autre personne qui essaie de contester l'approche de la super classe avec quelque chose de plus simple, mais encore une fois, la réponse la plus crédible déclare qu'il n'est pas possible de faire autrement, l'approche officielle non-xml est ladite approche de sous-classe.

Sources

[1] Comment mapper une classe à différentes tables à l'aide d'annotations hibernate/jpa

[2] Mapper deux tables identiques (même schéma ...) à la même entité dans Hibernate

[3] Comment mapper 2 tables identiques (mêmes propriétés) à 1 entité

[4] http://docs.jboss.org/hibernate/core/3.2/reference/en/html/mapping.html#mapping-entityname

[5] Hibernate 4: Mappage d'une classe Deux tables - Comment faire persister un objet sur les deux tables?

[6] Hibernate Annotation for Entity existant dans plus de 1 catalogue

34
mico

Cela fonctionne également en utilisant une entité par défaut et une autre:

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
   <class name="DomainModel.User, DomainModel"
     table="User1Object">  
         <id name="_id" access="field" column="id">
             <generator class="assigned"/>
         </id>
        <property name= ...>
 </class>
 <class name="DomainModel.User, DomainModel"
     table="User2Object" entity-name="User2Object">
         <id name="_id" access="field" column="id">
            <generator class="assigned"/>
         </id>
        <property name= ...>
</class>
</hibernate-mapping>

Pour celui par défaut, vous pouvez utiliser la méthode

_session.Save(user1)

et

_session.Save("User2Object", user2)

pour l'alternative.

3
LieT13

Vous pouvez le faire en utilisant la configuration:

  • Créez deux mappages pour la même classe d'entité name, mais donnez-leur une logique différente entity-name, et table nom.
  • Utilisez ensuite les méthodes Session où vous fournissez entityName comme paramètre pour distinguer les unes des autres.

Qu'est-ce que cela permet?

  • "Sous-typage virtuel"
  • Lorsque vous récupérez des données dans le type, vous devez en spécifier un entity-type ou l'autre (impliquant donc une table ou l'autre)
  • Lorsque vous modifiez des données et les enregistrez, vous devez spécifier les mêmes entity-type - une tentative de mise à jour avec un autre entity-type doit être rejeté par hibernate. Sinon, les entités modifiées auront déjà un identifiant rempli, donc hibernate essaiera de mettre à jour plutôt que d'insérer, mais cela échouera dans la base de données - essayez de mettre à jour des données qui n'ont jamais existé dans la table.
  • Cela conduit à la ségrégation - vous devez vous engager sur un type d'entité lorsque vous travaillez sur une entité ou une liste d'entités, et ne pouvez pas mélanger les deux. c'est-à-dire "sous-typage virtuel"

Quels sont les coûts?

  • Il donne un typage très faible. Le compilateur et le runtime n'ont aucune indication sur le vrai sous-type. Des erreurs attendent de se produire et peuvent être difficiles à déboguer.
  • Ce n'est pas standard. JPA a évité cela, je pense que ce n'est pas sur le radar pour l'inclusion, et pour une bonne raison.
  • Vous devez utiliser XML, pas des annotations.
  • Vous devez appeler des méthodes inhabituelles, y compris le paramètre "type d'entité".

Y a-t-il des avantages par rapport au sous-typage?

  • Aucun que je puisse voir

Devriez-vous le faire?

  • Je ne pense pas! Utilisez le sous-typage et le code standard.
1
Glen Best

Je sais que cette question a été posée il y a longtemps. Mais je voudrais suggérer une manière alternative, sans utiliser aucune des choses d'hibernation. Pour ceux qui ne veulent pas utiliser la configuration xml.

Déclarez une interface avec les méthodes getter et setter des colonnes communes, puis faites en sorte que vos classes d'entités remorqueuses implémentent cette interface. Laissez les annotations de mappage dans cette classe à deux entités comme d'habitude, puis dans votre code, vous pouvez appeler la méthode de cette interface à la place.

0
Qianlong

Bien que je n'ai jamais utilisé mais il existe un concept de table secondaire en hibernation. Et @SecondaryTables est l'annotation en hibernation par laquelle une entité peut mapper plusieurs tables pour récupérer les données. L'entité qui récupère les données doit avoir des annotations @SecondaryTables. Il associe la table secondaire sur la base de la clé primaire et étrangère et également sur la base de contraintes uniques.

Voici un exemple que j'ai trouvé après avoir fait google, vérifiez si cela vous aide à atteindre:

http://www.concretepage.com/hibernate/secondarytables_hibernate_annotation.php

0
Juned Ahsan