【问题标题】:How to do association fetching with restrictions in hibernate 4?如何在hibernate 4中进行关联获取限制?
【发布时间】:2014-10-09 12:27:59
【问题描述】:

我有根实体Hostel 及其单一关联User owner

当我获取 Hostel 实体时,我需要急切地获取 User owner,但只有所有者的 3 个属性:userIdfirstNamelastName

此外,在这个查询中,我不需要获取User owner 的一些关联。它们是:User 实体的avatarimages

现在我的条件查询是:

@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 cmets 之后,我会获取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。但我不想急切地从User owner 检索avatarimages,我描述了它。

如何更新我的查询以从 User owner 关联中延迟获取 avatarimages

此查询从 User owner 关联中获取所有属性,因此我的限制不起作用。

附言如果我不获取User owner 关联,那么一切正常。

【问题讨论】:

    标签: java hibernate hibernate-criteria


    【解决方案1】:

    这不是您向 Hibernate 指示 LAZY fetch 的方式:

    .setFetchMode("owner.avatar", FetchMode.SELECT)
    

    FetchMode.SELECT 用于在单独的选择中检索相关信息

    对于 LAZY,你应该设置:

    .setFetchMode("owner.avatar", FetchMode.LAZY)
    

    还有很多我没有真正理解的惯用语,例如:

    1. 为什么要创建投影来获取计数:

      Long count = (Long) criteria
              .setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY)
              .setProjection(Projections.rowCount()).uniqueResult();
      
    2. 然后将投影设置为null

      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 是实际的 hostel 引用,Hibernate 不会为这两个发出新的连接。它知道如何使用单个连接处理双向关联。

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-27
    • 2018-09-12
    • 1970-01-01
    • 2013-02-27
    • 1970-01-01
    • 2015-10-22
    相关资源
    最近更新 更多