0

I'm having a problem with Hibernate's Criteria API. For unknown reason adding a left-join type alias changes the resultset.

I want to recreate the following SQL query in Criteria API:

    select distinct f.*
    from form_instance i
    join form_value v on v.form_instance_id = i.id
    join form_field f on f.form_field_id = v.form_field_id
    where
    (f.id = ? and v.value = ?)
    or (f.id = ? and v.value = ?)

The mapping (only relevant fields) comes from legacy code (I haven't worked with xml mapping in hibernate nor composite ids).

FormInstance:

(I've tried disabling lazy loading, no effect)

    <set name="values" lazy="true" batch-size="200" cascade="all,delete-orphan" inverse="true"> 
      <key column="form_instance_id"/>
      <one-to-many class="FormValue" not-found="ignore" />
    </set>

FormValue:

    <composite-id>
      <key-many-to-one name="field"
            column="form_field_id"
            class="com.sales.model.FormField" />
      <key-many-to-one name="formInstance" column="form_instance_id" />
      <key-property column="value_index" name="valueIndex" />
    </composite-id>

FormField:

    <many-to-one class="com.sales.model.FormField" 
        column="parent_field_id" insert="false" 
        name="parentField" not-null="false" update="false"/>

I won't go into details about how exactly criteria are constructed, since It's not critical. Detached criteria is created for FormInstabnce.class and then some minor restrictions are added.

When I execute hibernateTemplate.findByCriteria(detachedCriteria, 1, 10) I get only 1 result, although when I try to count distinct root entities, the result is correct (2000+ results)

    criteria.setProjection(Projections.countDistinct(rootEntityId));
    Long result = (Long) dataObjectDAO.findByCriteria(criteria, 1).get(0);

(after this operation I reset projection and resultTransformer obvio

    criteria.setProjection(null);
    criteria.setResultTransformer(CRITERIA_RESULT_TRANSFORMER);

I've tried debugging this and the problem arises (changed result count) when I add alias to formValue:

detachedCriteria.createAlias("values", "values", CriteriaSpecification.LEFT_JOIN);

During debugging, I've dumped the queries that are executed and there is difference when I add the alias - this might hint someone more proficient in Hibernate to what's actually going on. I've replaced field lists with * to improve readability.

Without alias, correct result:

select * from ( 
    select * 
    from bank.form_instance this_ 
    where this_.product=? 
    order by this_.pf_date desc 
) 
where rownum <= ?

With alias, incorrect result (1 row):

select * from ( 
    select *
    from bank.form_instance this_ 
    left outer join bank.form_value values1_ on this_.id=values1_.form_instance_id 
    where this_.product=? and ((this_.user_name=?)) order by this_.pf_date desc 
) 
where rownum <= ?

select *
from bank.form_field formfield0_ 
where formfield0_.form_field_id in (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)

I've tried going deeper with debugging, but when I tried debugging on decompiled Hibernate classes my IDE desynchronized and it turned out impossible without additional work.

What is interesting is that the 2nd query searches only for 10 formFields, although there's like 180 formFields for every formInstance, and 10 is the value that's passed to searchByCriteria method.

I suspect that hibernate mapping is incorrect, but I'm not proficient enought to find out by myself. Any help would be deeply appreciated, I'm stuck on this problem for 2 days now and I'm getting really frustrated.

Best regards, Jony

Mikko Maunu
  • 41,366
  • 10
  • 132
  • 135
Jan Siekierski
  • 409
  • 6
  • 14
  • I see you used `DetachedCriteria.createAlias()` - could you try and use `DetachedCriteria.createCriteria()` instead? I'm not exactly sure what `createAlias()` does but `createCriteria()` works fine for me in a similar scenario. They have the same signature, too :-) – Oliver Jun 28 '16 at 08:16
  • Thanks for the suggestion, but the question is pretty old now. Sadly I didn't find the answer and had to abandon critetia api in favour of native sql because of the deadlines. – Jan Siekierski Jul 14 '16 at 20:09

0 Answers0