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?
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
[6] Hibernate Annotation for Entity existant dans plus de 1 catalogue
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.
Vous pouvez le faire en utilisant la configuration:
name
, mais donnez-leur une logique différente entity-name
, et table nom.Session
où vous fournissez entityName
comme paramètre pour distinguer les unes des autres.Qu'est-ce que cela permet?
entity-type
ou l'autre (impliquant donc une table ou l'autre)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.Quels sont les coûts?
Y a-t-il des avantages par rapport au sous-typage?
Devriez-vous le faire?
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.
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