-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 1 post ] 
Author Message
 Post subject: criteria: polymorphism and association OR-ing questions
PostPosted: Fri Aug 25, 2006 10:35 am 
Newbie

Joined: Fri Aug 25, 2006 10:18 am
Posts: 8
Location: England
Hibernate version:hibernate-3.1

I want to use Query by Criteria for all of my queries but I cannot figure out how to do a couple of things which I believe will be doable. I have spent a considerable amount of time reading the Hibernate books/docs/forums without being able to suss the appropriate technique.

Firstly I want to be able to 'OR' two criteria where one involves an association (see scenario 1) and secondly I want to be able to 'OR' an association from derived types which have the same association names (see scenario 2).

Can anyone help?

Scenario 1)

I have a class with an association and a member:

Code:
   class Class1 implements Serializable {

            private Long class1Pk;   // identifier

            private int classState;  // member

            private Other1 other1;   // association
    }

    class Other1 implements Serializable {

            private Long other1Pk;   // identifier

            private int otherState;  // member

            private Set class1s;     // association
    }


I want to write a quey which returns the Class1 instances where the Class1 instance has a particular state OR it has an associated Other1 instance with that state.

I tried the following:

Code:
    public static List findClass1sByState(final Integer state)
    {
        final Criteria class1Criteria = session.createCriteria(Class1.class);
        class1Criteria.add(Restrictions.eq("classState", state));

        final Criteria other1Criteria = class1Criteria.createCriteria("other1");
        other1Criteria.add(Restrictions.eq("otherState", state));

        return class1Criteria.list();
    }


This runs but results in SQL like the following:

Code:
    ...
    where
        this_.class_state = ?
        and other1.3_2_.other_state = ?
    ...


Question 1) How do I add the associated Criteria object to the original Criteria object such that it will result in a query which will 'OR' rather than 'AND' the two Criteria objects?


Scanario 2)

I have a Base class with two derived classes, Derived1 and Derived2, and each of the derived classes is associated with an Other1 class.

The class' members are as follows:

Code:
    class Base implements Serializable {

            private Long basePk;   // identifier
    }

    class Derived1 extends Base implements Serializable {

            private Other1 other1; // association
    }

    class Derived2 extends Base implements Serializable {

            private Other1 other1;  // association
    }

    class Other1 implements Serializable {

            private Long other1Pk;  // identifier

            private Set derived1s;  // association

            private Set derived2s;  // association
    }


I want to run a query to return a List of Base class instances where their derived classes are associated to an Other1 instance with a given primary key.

I tried:

Code:
    public static List findBasesByOther1Pk(final Long other1PkId)
    {
        final Criteria baseCriteria = session.createCriteria(Base.class);

        final Criterion classDerived1Criterion =  Restrictions.eq("class", Derived1.class);
        final Criterion other1Criterion1 = Restrictions.eq("other1.other1Pk", other1PkId);
        final LogicalExpression andExprDerived1 =  Restrictions.and(classDerived1Criterion, other1Criterion1);

        final Criterion classDerived2Criterion =  Restrictions.eq("class", Derived2.class);
        final Criterion other1Criterion2 = Restrictions.eq("other1.other1Pk", other1PkId);
        final LogicalExpression andExprDerived2 =  Restrictions.and(classDerived2Criterion, other1Criterion2);

        final LogicalExpression orExp = Restrictions.or(andExprDerived1, andExprDerived2);

        baseCriteria.add(orExp);
   
        return baseCriteria.list();
    }


Which resulted in SQL like the following:

Code:
    ...
    where
        (
            (
                case
                    when base1_1_.derived1_pk_fk is not null then 1
                    when base1_2_.derived2_pk_fk is not null then 2
                    when base1_.base_pk is not null then 0
                end=?
                and base1_1_.other1_fk=?
            )
            or (
                case
                    when base1_1_.derived1_pk_fk is not null then 1
                    when base1_2_.derived2_pk_fk is not null then 2
                    when base1_.base_pk is not null then 0
                end=?
                and base1_1_.other1_fk=?                             <<< I expected "and base1_2_.other1_fk=?"
            )
        )
    ...


This only found the Base class instances where their derived classes were Derived1 instances with the appropriate Other1 associated instances but missed the Derived2 instances.

I can fix this by changing the names of Derived1.other1 and/or Derived2.other1 so that they do not conflict (although I do not want to make this change), i.e:

Code:
    class Derived1 extends Base implements Serializable {

            /** persistent field */
            private Other1 other1FromDerived1;
    }

    class Derived2 extends Base implements Serializable {

            /** persistent field */
            private Other1 other1FromDerived2;
    }


And amending the query to:

Code:
    public static List findBasesByOther1Pk(final Long other1PkId)
    {
        final Criteria baseCriteria = session.createCriteria(Base.class);

        final Criterion other1ByDerived1Criterion = Restrictions.eq("other1FromDerived1.other1Pk", other1PkId);
        final Criterion other1ByDerived2Criterion = Restrictions.eq("other1FromDerived2.other1Pk", other1PkId);

        baseCriteria.add(Restrictions.or(other1ByDerived1Criterion, other1ByDerived2Criterion));
   
        return baseCriteria.list();
    }


Question 2) Is there a way of differentiating between the Derived1.other1 and Derived2.other1 without having to re-name the members? I would have expected the member names not to need to be restricted in any way.

Thanks in advance for any help are sorry if these are dumb questins - I'm new to Hibernate.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 1 post ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.