我有根实体Hostel
及其单一关联User owner
。
当我提取Hostel
实体时,我需要急切地提取User owner
,但只需提取所有者的3个属性:userId
,firstName
,lastName
。
此外,在此查询中,我无需获取User owner
的某些关联。它们是:avatar
和images
User
实体。
现在我的标准查询是:
@SuppressWarnings("unchecked")
public void findHostelBy(HostelSearch hs) {
Criteria criteria = currenSession().createCriteria(Hostel.class);
String country = hs.getCountry();
criteria.add(Restrictions.ge("endDate", Calendar.getInstance()));
if (StringUtils.notNullAndEmpty(country)) {
criteria.add(Restrictions.eq("country", country));
}
// making Hostel's associations lazy
criteria.setFetchMode("images", FetchMode.SELECT);
criteria.setFetchMode("requests", FetchMode.SELECT);
criteria.setFetchMode("feedbacks", FetchMode.SELECT);
criteria.setReadOnly(true);
criteria.addOrder(Order.desc("rating"));
// retrieve owner association
criteria = 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")))
.setFetchMode("owner.avatar", FetchMode.SELECT)
.setFetchMode("owner.images", FetchMode.SELECT);
Long count = (Long) criteria
.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY)
.setProjection(Projections.rowCount()).uniqueResult();
criteria.setProjection(null);
List<Hostel> hostels = criteria.list();
for (Hostel hostel : hostels) {
User owner = hostel.getOwner();
System.out.println("owner=" + owner);
}
}
在// retrieve owner association
评论之后,我提取User owner
关联。我通过以下方式将owner
的选择限制为3个属性:
Projections.projectionList()
.add(Projections.property("owner.userId"))
.add(Projections.property("owner.firstName"))
.add(Projections.property("owner.lastName")))
然后我让所有者的协会头像和图像变得懒惰:
.setFetchMode("owner.avatar", FetchMode.SELECT)
.setFetchMode("owner.images", FetchMode.SELECT);
我在线上获得例外
List<Hostel> hostels = criteria.list();
例外是:
Caused by: org.hibernate.TypeMismatchException: Provided id of the wrong type for class com.home.hostme.entity.Image. Expected: class java.lang.Long, got class java.lang.Integer
at org.hibernate.event.internal.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:134)
at org.hibernate.internal.SessionImpl.fireLoad(SessionImpl.java:1092)
at org.hibernate.internal.SessionImpl.internalLoad(SessionImpl.java:1019)
at org.hibernate.type.EntityType.resolveIdentifier(EntityType.java:672)
at org.hibernate.type.EntityType.resolve(EntityType.java:490)
at org.hibernate.engine.internal.TwoPhaseLoad.doInitializeEntity(TwoPhaseLoad.java:168)
at org.hibernate.engine.internal.TwoPhaseLoad.initializeEntity(TwoPhaseLoad.java:137)
at org.hibernate.loader.Loader.initializeEntitiesAndCollections(Loader.java:1107)
at org.hibernate.loader.Loader.processResultSet(Loader.java:963)
at org.hibernate.loader.Loader.doQuery(Loader.java:910)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:341)
at org.hibernate.loader.Loader.doList(Loader.java:2522)
at org.hibernate.loader.Loader.doList(Loader.java:2508)
at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2338)
at org.hibernate.loader.Loader.list(Loader.java:2333)
at org.hibernate.loader.criteria.CriteriaLoader.list(CriteriaLoader.java:124)
at org.hibernate.internal.SessionImpl.list(SessionImpl.java:1662)
at org.hibernate.internal.CriteriaImpl.list(CriteriaImpl.java:374)
at com.home.hostme.dao.impl.HostelDaoImpl.findHostelBy(HostelDaoImpl.java:112)
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)
... 51 more
根Hostel
实体的主键列是Integer,但Image
实体的主键是Long。但我不想急切地从avatar
检索images
或User owner
,而是我描述了它。
如何将我的查询更新为从avatar
关联延迟抓取images
和User owner
?
此查询从User owner
关联中提取所有属性,因此我的限制也不起作用。
P.S。如果我没有获取User owner
关联,那么一切正常。
答案 0 :(得分:0)
这不是你如何指导Hibernate关于LAZY的获取:
.setFetchMode("owner.avatar", FetchMode.SELECT)
FetchMode.SELECT用于在单独的选择
中检索关联的信息对于LAZY,你应该设置:
.setFetchMode("owner.avatar", FetchMode.LAZY)
还有很多我真正无法获得的东西,比如:
为什么要创建投影来获取计数:
Long count = (Long) criteria
.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY)
.setProjection(Projections.rowCount()).uniqueResult();
然后将投影设置为空
criteria.setProjection(null);
如果您想要一个拥有所有者但没有任何其他关联的旅馆列表,您只需标记以下内容:
.setFetchMode("owner.avatar", FetchMode.LAZY)
另一个选择是让所有关联LAZY并简单地指示在查询的基础上获取什么:
select h
from Hostel h
left join fetch h.owner o
虽然h.owner.avatar和h.owner.images有意义不被提取,但h.owner.hostel是实际的宿舍参考,Hibernate不会为这两个发布新的连接。它知道如何处理单个连接的双向关联。