Comment faire Hiberner récupérer toutes les propriétés de la racine de l'entité et seulement des propriétés spécifiques de l'entité associée?
J'ai de la racine de l'entité Hostel
et son association unique User owner
.
Lorsque j'extrais Hostel
entité j'ai besoin de ardemment récupérer User owner
, mais seulement owner
's 3 propriétés : nom d'utilisateur,firstName,lastName.
Pour l'instant mes critères de requête est :
Criteria criteria = currenSession().createCriteria(Hostel.class);
criteria.add(Restrictions.ge("endDate", Calendar.getInstance()));
if (StringUtils.notNullAndEmpty(country)) {
criteria.add(Restrictions.eq("country", country));
}
Long count = (Long) criteria
.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY)
.setProjection(Projections.rowCount()).uniqueResult();
criteria.setFetchMode("owner", FetchMode.SELECT);
criteria.addOrder(Order.desc("rating"));
//needed to reset previous rowCount projection
criteria.setProjection(null);
//retrieve owner association
criteria.createAlias("owner", "owner", JoinType.LEFT_OUTER_JOIN)
.setProjection(
Projections.projectionList()
.add(Projections.property("owner.userId"))
.add(Projections.property("owner.firstName"))
.add(Projections.property("owner.lastName")));
criteria.setResultTransformer(Criteria.ALIAS_TO_ENTITY_MAP);
Prochaine, je ne criteria.list()
et je reçois l'instruction sql qui sélectionne uniquement owner
's 3 propriétés, comme spécifié dans la liste de projection. Mais il ne sélectionnez pas la propriété de la racine Hostel
entité.
Requête générée est:
select
owner1_.user_id as y0_,
owner1_.firstName as y1_,
owner1_.lastName as y2_
from
HOSTEL this_
left outer join
USER owner1_
on this_.owner_fk=owner1_.user_id
where
this_.end_date>=?
and this_.country=?
order by
this_.rating desc limit ?
Cette requête ne fonctionne pas parce qu'il renvoie cinq Map
s qui sont vides. Cinq cartes sont parce qu'il y a cinq Hostel
les lignes qui correspondent à la condition where. J'ai créé simple requête sql et il fonctionne très bien si le problème est uniquement un problème ici.
Comment la force hibernate pour aller chercher toutes les propriétés de la racine Hostel
entité et à seulement 3 propriétés des associés User owner
entité?
MODIFIER
J'ai essayé d'utiliser getSessionFactory().getClassMetadata(Hostel.class)
mais il a donné une erreur à propos de la cartographie enum dans Hostel
. J'ai donc de secours à la liste Hostel
manuellement les propriétés. Pour l'instant mes critères de requête est:
//retrieve owner association
criteria.createAlias("owner", "owner", JoinType.LEFT_OUTER_JOIN);
criteria.setProjection(Projections.projectionList()
.add(Projections.property("hostelId"))
.add(Projections.property("address"))
.add(Projections.property("country"))
.add(Projections.property("region"))
.add(Projections.property("gender"))
.add(Projections.property("owner.userId"))
.add(Projections.property("owner.firstName"))
.add(Projections.property("owner.lastName")));
List<Hostel> hostels = criteria.list();
for (Hostel hostel : hostels) { //at this line I get error java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to com.home.hostme.entity.Hostel
User owner = hostel.getOwner();
System.out.println("owner=" + owner);
}
Remarque que j'ai enlevé ALIAS_TO_ENTITY_MAP
résultat transformateur. Cela a généré une telle requête mysql :
select
this_.hostel_id as y0_,
this_.address as y1_,
this_.country as y2_,
this_.region as y3_,
this_.gender as y4_,
owner1_.user_id as y5_,
owner1_.firstName as y6_,
owner1_.lastName as y7_
from
HOSTEL this_
left outer join
USER owner1_
on this_.owner_fk=owner1_.user_id
where
this_.end_date>=?
and this_.country=?
order by
this_.rating desc limit ?
À boucle for-each obtenir une telle erreur:
java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to com.home.hostme.entity.Hostel
at com.home.hostme.dao.impl.HostelDaoImpl.findHostelBy(HostelDaoImpl.java:168)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:317)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:155)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
at com.sun.proxy.$Proxy64.findHostelBy(Unknown Source)
at com.home.hostme.service.HostelService.findHostelBy(HostelService.java:27)
at com.home.hostme.service.HostelService$$FastClassByCGLIB$$74db5b21.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:698)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:96)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:260)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:94)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:631)
at com.home.hostme.service.HostelService$$EnhancerByCGLIB$$7af3bc10.findHostelBy(<generated>)
at com.home.hostme.web.hostel.HostelController.doSearch(HostelController.java:94)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:219)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:132)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:104)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:745)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:686)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:80)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:925)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:856)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:936)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:838)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:647)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:812)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:953)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1041)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:603)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:312)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
Cette erreur signifie que je n'ai pas de type de Hostel
dans la liste hostels
.
J'ai même essayé de trouver d'éléments dans la liste des auberges de " avec ce:
List hostels = criteria.list();
System.out.println("firstRow.class=" + hostels.get(0).getClass());
De l'imprimer:
firstRow.class=class [Ljava.lang.Object;
Puis j'ai essayé de mettre ALIAS_TO_ENTITY_MAP
pour les nouveaux ProjectionList, mais la liste des auberges de' a:
[{}, {}, {}, {}, {}]
Cinq vider les cartes. Cinq parce qu'il y a 5 lignes en db(table de l'auberge) correspondant à la clause where.
Puis j'ai supprimé la projection liste complète et mise en veille prolongée consulté le 5 auberges et 5 associés User owner
s et owner
'images comme prévu.
LE PROBLÈME est de savoir comment arrêter d'hiberner récupérer associés Image
entité associée User owner
. Le mieux serait de récupérer uniquement 3 accessoires associés User owner
.
Merci!
Je ne peux pas changer entités . J'ai besoin de le faire dans les critères de l'api. J'ai essayé d'appeler la méthode setFetchMode(PARESSEUX) sur
owner
association, mais il récupère tous les accessoires de User owner
avec impatience de toute façonS'il vous plaît pouvez-vous préciser quelques petites choses: 1. S'il vous plaît pourriez-vous mettre à jour votre question d'inclure le code de l'Auberge et de l'Utilisateur de la classe? 2. Pourquoi avez-vous de l'utilisation de critères? Serge a donné une bonne réponse pour les requêtes HQL ci-dessous? 3. Pourquoi vous voulez seulement ces champs à partir de l'utilisateur? Existe-il d'autres champs de l'utilisateur que vous pensez cause d'un problème de performance? Merci.
Oui,
User
entité a Image
association avec FetchMode.IMPATIENT et je n'ai pas besoin d'aller chercher Image
avec impatience la seule dans mon cas. HQL est possible, mais j'ai pensé que des critères est la bonne façon de faire.Merci pour l'info. Pouvez-vous également préciser - ce que vous faites avec les données une fois que vous avez récupéré? Voulez-vous l'Auberge des objets liés à des objets Utilisateur, ou avez-vous juste besoin de valeurs de propriétés spécifiques de chaque Auberge de jeunesse et les associés de l'Utilisateur?
OriginalL'auteur Volodymyr Levytskyi | 2014-08-16
Vous devez vous connecter pour publier un commentaire.
Vous pouvez le faire avec une requête directe :
génère le SQL comme :
avec tous les champs de l'Auberge, et uniquement les champs obligatoires de l'Utilisateur.
La liste obtenue avec
criteria.list()
est unList<Object[]>
dont les lignes sont[ Hostel, Integer, String, String]
Vous pouvez obtenir quelque chose à l'aide
Criteria
, maisCriteria
sont plus strictes que les requêtes. Je ne pouvais pas trouver une API qui permet de mélanger des entités et des champs. Donc, autant que je sache, il n'est pas possible d'obtenir les lignes contenant une entité (Auberges de jeunesse) et des champs séparés par une association (propriétaire.l'identifiant, le propriétaire.prénom, propriétaire.de nom).La seule façon que je peux imaginer serait explicitement la liste de tous les champs des Auberges de jeunesse :
Vous pouvez automatiser un peu en utilisant les Métadonnées (n'oubliez pas l'id ...) - remarque : j'utilise un alias de projection uniquement pour être en mesure, plus tard, d'utiliser une classe wrapper, si vous utilisez directement les valeurs scalaires, vous pouvez omettre le
Projection.alias
:De cette façon génère correctement
Mais vous ne serez pas en mesure d'utiliser
criteria.setResultTransformer(Criteria.ALIAS_TO_ENTITY_MAP)
car le jeu de résultats n'est pas exactement l'image des champs deHostel
(même sans les alias).En fait, la liste est un
List<Object[]>
avec les lignes contenant tous les champs deHostel
suivi par les 3 champs obligatoires à partir deowner
.Vous devrez ajouter une classe wrapper contenant un
Hostel
et les 3 autres champs d'utiliser unAliasToBeanResultTransformer
et d'une vraieHostel
objets :Et puis vous pouvez l'écrire correctement :
J'ai pu vérifier que lorsqu'il n'y a pas de propriétaire
hostel.getOwner()
est null, et quand il y en a un,hostel.getOwner().getId()
est égal àgetOwner_id()
et que cet accès ne permet pas de générer une requête supplémentaire. Mais tout accès à un autre domaine de lahostel.getOwner()
, mêmefirstName
oulastName
génère un parce que leUser
entité n'a pas été chargé dans la session.L'utilisation la plus courante devrait être :
Vous pouvez voir mon edit.
il fonctionne maintenant (dans mes tests ...), mais j'ai dû utiliser une classe wrapper autour de l'Auberge et les 3 champs du propriétaire. Post édité.
Comment carte
Hostel hostel
deHostelWrapper
à la liste de projection dans les critères?Je ne suis pas sûr de comprendre votre dernière question. Je l'ai mis dans la projection de la liste de tous les champs de
Hostel
alias avec leur nom, et les 3 champs deUser
, puis leAliasToBeanResultTransformer
transforme chaque ligne dans unHostelWrapper
contenant unHostel
et les 3 autres champs. J'ai édité mon post pour plus de normal utilisation.OriginalL'auteur Serge Ballesta
@Serge Ballesta résolu mon problème mais ici, c'est mon dernier code de travail:
Et mon
HostelWrapper
est :Ce
HostelWrapper
est utilisé parAliasToBeanResultTransformer
à la carte hibernate resultset à des entités.Ma conclusion finale est que les requêtes HQL est bonne chose à faire lorsque vous voulez mettre en projection sur l'association.
Avec
AliasToBeanResultTransformer
vous êtes lié à des noms de propriétés et avec hql est le même. Avantage est que les requêtes HQL est beaucoup plus facile à écrire.OriginalL'auteur Volodymyr Levytskyi
Selon mon observation, vous ne pouvez pas obtenir le résultat que par vous avez besoin.
Nous pouvons le faire en utilisant les étapes suivantes:
Veuillez modifier le code comme ci-dessous
S'il vous plaît essayer et crois-moi savoir.
Dans ce projectionList seulement j'ai ajouté de l'Auberge params. Nous avons donc besoin d'ajouter propriétaire de référence sur le dessus de cela.
J'ai fait comme vous avez dit et reçu zéro lignes
Veuillez coller la requête qui est généré
Les mêmes que celles prévues à l'exception de toutes les auberges, les propriétés sont répertoriées. La requête itsef est ok, mais le résultat est zéro, ce qui est étrange que les données sont dans la base de données
OriginalL'auteur Siva Kumar