Question

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. The main object is a Group which has a list of Property instances, and each Property containing a list of 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. 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. 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)

B) When making the Query, for example, a SQL, it shows in the log the SQL code we want. 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.

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>
Was it helpful?

Solution

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.

Because of this and the nested objects, we had also bad implementations of the hashCode() and equals() methods which Hibernate uses.

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top