我有根实体Hostel
及其单一关联User owner
。
当我获取Hostel
实体时,我需要热切地获取User owner
,但是只有它owner
的3个属性:userId,firstName,lastName。
现在,我的条件查询是:
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);
接下来,我criteria.list()
得到了sql语句,该语句仅选择owner
投影列表中指定的3个属性。但是它不会选择根Hostel
实体的任何属性。生成的查询是:
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 ?
该查询不起作用,因为它返回了五个Map
为空的。五个映射是因为有五行Hostel
匹配where条件。我创建了简单的sql查询,它工作正常,因此问题仅在这里。
如何强制hibernate获取根Hostel
实体的所有属性以及关联User owner
实体的仅3个属性?
*我尝试使用 *EDIT
,getSessionFactory().getClassMetadata(Hostel.class)
但它给出了有关在中映射枚举的错误Hostel
。因此,我后退以Hostel
手动列出属性。现在,我的条件查询是:
// 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);
}
请注意,我删除了ALIAS_TO_ENTITY_MAP
结果转换器。这产生了这样的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 ?
在for-each循环中得到这样的错误:
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)
这个错误表示我没有Hostel
在结果列表中输入文字hostels
。我什至尝试用以下方法在结果列表“旅馆”中找出元素的类别:
List hostels = criteria.list();
System.out.println("firstRow.class=" + hostels.get(0).getClass());
它打印:
firstRow.class=class [Ljava.lang.Object;
然后,我尝试设置ALIAS_TO_ENTITY_MAP
新的ProjectionList,但结果列表“旅馆”为:
[{}, {}, {}, {}, {}]
五张空的地图。五,因为db(table hostel)中有5行与where子句匹配。
然后我完全删除投影列表和hibernate检索5个旅馆和5个相关联的User owner
S和owner
的图像作为预期。
问题是如何停止hibernate检索关联的关联Image
实体User owner
。最好的方法是仅获取3个相关联的道具User owner
。
谢谢!
您可以通过直接查询来做到这一点:
Query query = session.createQuery("SELECT hostel, owner.id, owner.firstname, "
+"owner.lastname FROM Hostel hostel LEFT OUTER JOIN hostel.ower AS owner");
List list = query.list();
生成一个SQL,如:
选择hostel0_.id作为col_0_0_,user1_.id作为col_1_0_,user1_.firstname作为col_2_0_,user1_.lastname作为col_3_0_,hostel0_.id作为id1_0_,hostel0_.name作为name2_0_,…,hostel0_.owner_id作为user_id4_0_外部联接user1_.id
= hostel0_.owner_id上的用户user1_
包含Hostel的所有字段,以及User的所有必填字段。
用获得的名单criteria.list()
是List<Object[]>
其行是 [ Hostel, Integer, String, String]
您可以使用来获取某些内容Criteria
,但Criteria
要比查询更严格。我找不到允许混合实体和字段的任何API。据我所知,不可能获得包含实体(旅馆)和与关联(owner.userId,owner.firstName,owner.lastName)分开的字段的行。
我能想象的唯一方法是明确列出Hostels的所有字段:
criteria.createAlias("owner", "owner", JoinType.LEFT_OUTER_JOIN)
.setProjection(
Projections.projectionList()
.add(Projections.property("hostelId"))
.add(Projections.property("country"))
.add(Projections.property("endDate"))
...
... all other properties from Hostel
...
.add(Projections.property("owner.userId"))
.add(Projections.property("owner.firstName"))
.add(Projections.property("owner.lastName")));
您可以通过使用元数据(不要忘记id
…)来实现一些自动化(注意:…):我使用别名投影只是为了以后可以使用包装器类,如果直接使用标量值,则可以安全地省略的Projection.alias
:
ProjectionList hostelProj = Projections.projectionList();
String id = sessionFactory.getClassMetadata(Hostel.class)
.getIdentifierPropertyName();
hostelProperties.add(Projections.alias(Projections.property(id),id));
for (String prop: sessionFactory.getClassMetadata(Hostel.class).getPropertyNames()) {
hostelProperties.add(Projections.alias(Projections.property(prop), prop));
}
Criteria criteria = session.createCriteria(Hostel.class);
criteria.createAlias("owner", "owner", JoinType.LEFT_OUTER_JOIN);
criteria.setProjection(
Projections.projectionList()
.add(hostelProj)
.add(Projections.property("owner.id"))
.add(Projections.property("owner.firstName"))
.add(Projections.property("owner.lastName")));
List list = criteria.list();
这样正确生成
从酒店this_中选择this_.id作为y0_,this_.name作为y1_,…,this_.user_id作为y3_,owner1_.id作为y4_,owner1_.firstname作为y5_,owner1_.lastname作为y6_,在this_上从外部加入用户owner1_
.user_id = owner1_.id
但是您将无法使用,criteria.setResultTransformer(Criteria.ALIAS_TO_ENTITY_MAP)
因为结果集不完全是来自字段的图像Hostel
(即使没有别名)。实际上,列表是List<Object[]>
带有行的,其中包含所有来自的单独字段,Hostel
然后是来自的3个必填字段owner
。
您将需要添加一个包含a Hostel
和3个其他字段的包装器类,以使用an AliasToBeanResultTransformer
和获取true
Hostel
对象:
public class HostelWrapper {
private Hostel hostel;
private int owner_id;
private String owner_firstName;
private String owner_lastName;
public HostelWrapper() {
hostel = new Hostel();
}
public Hostel getHostel() {
return hostel;
}
public void setId(int id) {
hostel.setId(id);
}
public void setOwner(User owner) {
hostel.setOwner(owner);
}
// other setters for Hostel fields ...
public int getOwner_id() {
return owner_id;
}
public void setOwner_id(Integer owner_id) {
// beware : may be null because of outer join
this.owner_id = (owner_id == null) ? 0 : owner_id;
}
//getters and setters for firstName and lastName ...
}
然后您可以成功编写:
criteria.setResultTransformer(new AliasToBeanResultTransformer(HostelWrapper.class));
List<HostelWrapper> hostels = criteria.list();
Hostel hostel = hostels.get(0).getHostel();
String firstName = hostels.get(0).getFirstName();
我可以确认的是,当没有主人hostel.getOwner()
是空的,当有一个,hostel.getOwner().getId()
等于getOwner_id()
和该访问不产生任何额外的查询。但是,任何访问的其他领域hostel.getOwner()
,甚至firstName
或lastName
产生,因为一个User
实体并没有在会议上加载。
最常见的用法应该是:
for (HostelWrapper hostelw: criteria.list()) {
Hostel hostel = hostelw.getHostel();
// use hostel, hostelw.getOwner_firstName and hostelw.getOwner_lastName
}
我有根实体及其单个关联。 当我获取实体时,我需要急切地获取,但只有的3个属性:userId、afstName、lastName。 现在我的标准查询是: 接下来,我执行,我得到了sql语句,它只选择了投影列表中指定的的3个属性。但它不选择根<code>Hostel</code>实体的任何属性。生成的查询为: 此查询不起作用,因为它返回五个空的。五个映射是因为有五个<code>Hostel</code
问题内容: 我收到一个包含30个字段的JSON,而我的实体是根据此JSON构建的。问题是:不应更新两个字段(两个日期)。 如果使用,两个字段都会更新。 如何避免更新这两个字段? 也许使用criteria.Example? 没有我写大量的HQL,有什么方法可以做到这一点吗? 问题答案: 本文非常详细地解释了您的问题,但我也将在这里进行总结。 如果您永远不想更新这两个字段,则可以将它们标记为: 当你将
我想我有两个实体具有双向的和关联: ——有很多-- 我想选择实体,其中所有关联的实体都将设置为 例如,如果我有以下数据: 起源: 孩子: 我想要一个HQL或JPQL查询,它返回1的实体。 知道吗?
关联实体和关联关系属性有什么区别?在我的一本名为《现代数据库管理》(Hoffer,第11版)的书中,作者陈述了两者之间的区别。然而,它并没有真正解释为什么会有差别,相反,它只是给出了它们是如何不同的例子。 据我所知,一个有一个属性关联的关系是一个关联关系属性,并用一条虚线表示一个圆角矩形,该矩形内有该属性。而关联实体是描述关系的多个属性。两者都只能用于ER图解中的多对多关系。我的思维过程正确吗?
我在两个实体之间有双向或父/子关系: 我要选择没有的所有或的属性设置为的。 我使用的是。
问题内容: 我有一个具有多个属性的核心数据实体,并且想要一个属性中所有对象的列表。我的代码如下所示: 但这给了我一个NSException错误,我不知道为什么,或者我应该怎么做。我已经阅读了NSFetchRequest类的描述,但从中讲不出来。 任何建议,将不胜感激。 编辑:从Bluehound获得提示后,我将代码更改为: 运行时错误消失了,但我仍然不知道它是否有效,因为我不确定如何将列表转换为字