简体   繁体   English

Hibernate无需询问即可进行多对一检索

[英]Hibernate retrieves many-to-one without asking

we have a big problem in our development team. 我们的开发团队遇到了一个大问题。

We are using Hibernate and we have some entities which are related in two transitive one-to-many relations. 我们正在使用Hibernate,并且我们有一些与两个可传递的一对多关系相关的实体。 The main object is a Group which has a list of Property instances, and each Property containing a list of Values. 主要对象是一个Group,它具有一个Property实例列表,每个Property包含一个Values列表。

(The mappings are down ahead) (映射向下)

We have two main problems: 我们有两个主要问题:

A) When making a HQL Query, Criteria Query or SQLQuery it doesn't matter the conditions applied in JOINs or WHERE clauses, Hibernate always retrieves for us all the underlying objects. A)进行HQL查询,条件查询或SQLQuery时,在JOIN或WHERE子句中应用的条件并不重要,Hibernate始终为我们检索所有基础对象。 For example, if I make a Criteria or SQL getting only the Group objects, Hibernate comes and (lazy or not) gets all the Property and Value instances too. 例如,如果我使一个Criteria或SQL仅获取Group对象,那么Hibernate就会来(并且无论是否懒惰)也将获取所有的Property和Value实例。 We want to control this. 我们要控制它。 We want to do left joins and get only the properties with no values inside (Hibernate removes these properties with no value) 我们想做左联接,只获取内部没有值的属性(Hibernate删除这些没有值的属性)

B) When making the Query, for example, a SQL, it shows in the log the SQL code we want. B)进行查询(例如SQL)时,它会在日志中显示所需的SQL代码。 Everything seems perfect. 一切似乎都很完美。 But after that it brings every instance in the list without applying conditions, getting them only by id, and we can assure this because with lazy="true" we see the "load many-to-one" queries in the log. 但是之后,它不使用条件就将列表中的每个实例带入列表,仅通过id获取它们,因此我们可以保证,因为使用lazy =“ true”时,我们会在日志中看到“加载多对一”查询。

Is there something we can do in hibernate config, fetching mode/strategy, the mappings configuration or anywhere? 在休眠配置,获取模式/策略,映射配置或其他任何地方,我们可以做些什么吗? I'm thinking on going on Result transformers now. 我正在考虑现在进行结果转换器。

I would be grateful if someone coud give me a hint or tell me where to find a solution to this problem. 如果有人给我提示或告诉我在哪里可以找到该问题的解决方案,我将不胜感激。 We are confused about how to get this, but it must be a way. 我们对如何获得此信息感到困惑,但这必须是一种方法。

Thanks in advance 提前致谢

Query: 查询:

Criteria lstCriterios = this.getSession().createCriteria(CardGroup.class, CARD_GROUP)
            .add(Restrictions.eq(ID_CATEGORY, idCategory));

    lstCriterios.createAlias("listProperty", "listProperty", CriteriaSpecification.LEFT_JOIN);

    if (clusterId != null) {
        lstCriterios.add(Restrictions.or(
                Restrictions.isNull("listPropertyValue" + ".value"),
                Restrictions.and(Restrictions.eq("listPropertyValue" + ".clusterId", clusterId),
                        Restrictions.eq("listPropertValue" + ".companyWarehouseId", idCompanyWarehouse))));
        lstCriterios
                .createAlias("listProperty" + "." + "listPropertyValue", "listPropertyValue",
                        CriteriaSpecification.LEFT_JOIN,
                        Restrictions.eq("listPropertyValue" + ".clusterId", clusterId));
    } else {
        lstCriterios.createAlias("listProperty" + ".listPropertyValue", "listPropertyValue",
                CriteriaSpecification.LEFT_JOIN);
    }

    lstCriterios.add(Restrictions.eq(ID_CATEGORY, idCategory));
    lstCriterios.add(Restrictions.eq("listProperty" + ".groupId", idGroup));
    lstCriterios.setResultTransformer(CriteriaSpecification.DISTINCT_ROOT_ENTITY);
    /*
     * Sorting
     */
    lstCriterios.addOrder(Order.asc("order"));
    lstCriterios.addOrder(Order.asc("listProperty" + ".order"));


    lstCriterios.addOrder(Order.asc("listPropertyValue"+ ".clusterId")); // Agrupacion, podría ser nulo
    lstCriterios.addOrder(Order.asc("listPropertyValue"+ ".propertyId")); // Propiedad
    lstCriterios.addOrder(Order.asc("listPropertyValue"+ ".id"));

    return lstCriterios.list();

Group mapping: 组映射:

<list name="listProperty" 
        table="FICHA_PROPIEDAD" schema="${db2.siglo.schema}"
        inverse="false" cascade="all" >

        <key column="ID_FICHA_GRUPO" not-null="false" />
        <list-index column="ORDEN" base="1"/>

        <one-to-many
            class="com.company.aslo.appwebsiglo.model.card.property.property.CardProperty" />
</list>

Property mapping: 属性映射:

<bag name="listPropertyValue" 
        table="FICHA_PROPIEDAD_VALOR" schema="${db2.siglo.schema}" 
        inverse="false" cascade="all">

        <key column="ID_FICHA_PROPIEDAD" not-null="false" />
        <one-to-many
            class="com.company.aslo.appwebsiglo.model.card.propertyvalue.propertyvalue.CardPropertyValue" />
</bag>

It seems like our model design was bad and we didn't realize that if the DB table FICHA_PROPIEDAD_VALOR has Composite Key we can't map only one of the attributes in the composite key, because it brings us unexpected results. 似乎我们的模型设计很糟糕,并且我们没有意识到,如果数据库表FICHA_PROPIEDAD_VALOR具有Composite Key,我们将无法仅映射复合键中的一个属性,因为它给我们带来了意想不到的结果。

Because of this and the nested objects, we had also bad implementations of the hashCode() and equals() methods which Hibernate uses. 由于这个原因和嵌套的对象,Hibernate使用的hashCode()和equals()方法的实现也很糟糕。

I had solved this previously with a ResultTransformer getting the rows from a SQLQuery, but we got the Hibernate solution after that refactoring and changing the design of our model. 我以前用ResultTransformer解决了此问题,该方法从SQLQuery获取行,但是在重构和更改模型的设计之后,我们得到了Hibernate解决方案。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM