2009-09-15 6 views
9

Problème

J'ai un @MappedSuperclass appelé Data en tant que parent de chaque entité dans ma base de données. Il contient des attributs communs comme Id etc. J'ai alors une entité qui étend les données qui est également un @MappedSuperclass en raison de la fonctionnalité commune de ses sous-classes. Le mappage dans ma base de données est correct.Sélection MappedSuperclass de la base de données (Hibernate)

Voici un exemple de ma hiérarchie

 
@MappedSuperclass 
Data 
| @MappedSuperclass 
+- Employee 
|  | @Entity 
|  +- FullTimeEmployee 
|  | @Entity 
|  +- PartTimeEmployee 
| @Entity 
+- Store 

Les tables sont correctement mis en correspondance:

 
FullTimeEmployee 
PartTimeEmployee 
Store 

Y at-il de toute façon d'interroger la base de données pour toutes les sous-classes d'employés (FullTimeEmployee, PartTimeEmployee) comme des instances de l'employé sans faire référence au nom des sous-classes dans la requête?

Quelque chose comme

List<Employee> allEmployees = getAllEmployees(); 

L'idée est que chaque fois que je décide de créer une autre sous-classe des employés (à savoir AllDayEmployee) Je ne vais pas devoir changer la requête d'inclure le nom.


Solution

Ainsi, comme Gregory a souligné à juste titre, ce n'est pas possible avec @MappedSuperclass. Je l'ai donc changé en @Entity et, comme je voulais conserver une table pour chaque sous-classe, j'ai utilisé InheritanceType.JOINED.

donc la hiérarchie ci-dessus est maintenant

 
@MappedSuperclass 
Data 
| @Entity 
| @Inheritance(strategy=InheritanceType.JOINED) 
+- Employee 
|  | @Entity 
|  +- FullTimeEmployee 
|  | @Entity 
|  +- PartTimeEmployee 
| @Entity 
+- Store 

Et les tables sont encore:

 
FullTimeEmployee 
PartTimeEmployee 
Store 

Alors maintenant, pour obtenir tous les employés que j'appelle simplement:

entityManager.createQuery("from Employee").getResultList(); 
+0

si je besoin de deux différents '@ SequenceGenerator' pour FullTimeEmployee et PartTimeEmployee (j'utilise Oracle séquences)? En tant qu'entité, je dois spécifier '@ Id' sur la classe Employee. – drakyoko

Répondre

8

Non si vous utilisez

@MappedSuperclass

La raison en est que lorsque vous définissez la classe de base comme @MappedSuperclass, il n'y a pas de table généré pour la classe de base, au lieu toutes les propriétés sont reproduites dans le béton les tables. Dans votre exemple, seules les tables FullTimeEmployee, PartTimeEmployee et Store existent.

Si vous souhaitez pouvoir interroger des entités de classe de base, vous devez sélectionner un mappage différent pour les classes de base. Utilisez l'annotation @Inheritance sur la classe de base et sélectionnez l'une des 3 stratégies de mappage possibles - TABLE SINGLE, TABLE PAR CLASS ou JOINED

0

Oui

FROM Employee WHERE Employee.<employee only properties> = someValue 

Mais seulement, comme les autres l'ont dit ici, si l'entité Employee est mappée. Vous n'avez même pas besoin de le mapper sur sa propre table. Voir les stratégies de cartographie dans Hibernate.

+0

+1 Oui. Dans Hibernate, vous pouvez sélectionner une classe abstraite, vous obtiendrez également toutes les sous-classes. L'exemple donné est de faire une requête pour Object, cela retournera toute la base de données! :-) – KLE

+0

Étant donné que Employee est une classe abstraite qui a une annotation @MappedSuperclass, je veux obtenir toutes les instances de sous-classe de Employee. La requête "from Employee" renvoie une exception QuerySyntaxException: l'employé n'est pas mappé " – pek

+0

Veuillez voir ma réponse pour savoir pourquoi cela ne fonctionnera pas avec @MappedSuperclass –

0

Je semble pouvoir faire cela (bien que j'utilise InheritanceType.JOINED) avec hibernate 5.0.8 , java 1.8.0_73 et Oracle 12c - soit je suis malentendu ou peut-être hiberner a changé ..

je l'hierarhcy suivante:

@MappedSuperclass 
@Inheritance(strategy=InheritanceType.JOINED) 
CommonRoot 
| 
| @MappedSuperclass 
+- Mapped 
     | @Entity(name="Concrete1") 
     | @Table(name="CON1") 
     +- Concrete1 
     | 
     | @Entity(name="Concrete2") 
     | @Table(name="CON2") 
     +- Concrete2 

Et je peux faire la HQL suivante:

SELECT entityId FROM com.hibernatetest.Mapped ORDER BY entityId ASC 

qui donne ces deux instructions SQL:

select concrete2x0_.entityId as col_0_0_ from CON2 concrete2x0_ order by concrete2x0_.entityId ASC 
select concrete1x0_.entityId as col_0_0_ from CON1 concrete1x0_ order by concrete1x0_.entityId ASC 

et l'avertissement

WARN: HHH000180: FirstResult/maxResults specified on polymorphic query; applying in memory! 

Je ne sais pas ce qu'ils veulent dire que, comme cela peut se faire avec SQL comme:

(select entityId from CON2 
union all 
select entityId from CON1) 
order by entityId ASC 

(Et vous pouvez également ajouter des clauses limite/ROWNUM que si vous le désirez, bien que cela devient un peu maladroit:

select * from (
(select * from (select entityId from CON2 order by entityId ASC) where rownum <= 10) 
UNION ALL 
(select * from (select entityId from CON1 order by entityId ASC) where rownum <= 10) 
) where rownum <= 10 order by entityId ASC 

Je ne sais pas pourquoi veille prolongée ne devrait pas être en mesure de le faire -. pourrait suggérer à eux)

Questions connexes