4 Replies Latest reply on Dec 3, 2010 10:47 AM by rogermorituesta.rogermori.yahoo.com

    hql and polymorphism

    flopsi

      hi everybody,


      i defined a hibernate entity with a polymorphic object property so the property's type is a base class and various object types can be assigned.
      Everything worked out fine since now, but now i want to perform an hql query with a join like:


      select objA from classA objA inner join fetch objA.prop objB ...


      now in the result objA.prop is always an object of the base class (of course you might say), but i needed it to be the right subclass to be able to fetch all properties. casting to the subclass results in a ClassCastException.


      is it possible to rewrite the query or do some other tricks so i retrieve an object of the right sublass here? of course i want to avoid executing an extra query for every result record...
      by the way, i use table-per-class (joined) mapping strategy.


      thanks a lot for opening my eyes,
      best regards,
      flo

        • 1. Re: hql and polymorphism
          flopsi
          okay, declaring the base class abstract seems to force hibernate to look for subclasses. unfortunately this has some impact on the rest of my application, so the question remains:
          is ther another way to force hibernate to do so?

          thx + regards
          flo
          • 2. Re: hql and polymorphism
            rogermorituesta.rogermori.yahoo.com

            ...but i needed it to be the right subclass to be able to fetch all properties. casting to the subclass results in a ClassCastException.

            A polymorfic hql result set already contains runtime instances of the subclasses. So no casting is required.


            If you want to query upon a specific subclass add a where clause to your hql.


            Roger.


            • 3. Re: hql and polymorphism
              flopsi
              hi roger,
              maybe i miss something. I tried using the 'class' attribute like

              select objA from classA objA inner join fetch objA.prop objB where objB.class=:classId

              with binding the simple class name to the :classId parameter, but an exception was thrown:
              java.lang.String cannot be cast to java.lang.Integer

              the generated sql looks like:
              ...
                      and case
                          when objB_1_.id is not null then 1
                          when objB_2_.id is not null then 2
                          when objB_.id is not null then 0
                      end=?

              where objB_1_ and objB_2_ reference the subclass tables as i can see in the select. so maybe binding 0, 1 or 2 to the :classId param would help.
              but how do i find out the correct number? is the hibernate generated statement fix so i can rely on the numbers shown here? or is it possible on the next execution the numbers have changed?

              is there maybe another way to specify the concrete class?

              thanks a lot
              best regards
              flo
              • 4. Re: hql and polymorphism
                rogermorituesta.rogermori.yahoo.com

                Hi Florian:


                Dealing with addresses (Geographic, email, web, phone, etc), I have a similar case with inheritance type JOINED. Yet, I have added a string column and a pre persist method to the base class in order to store the class name via entity listener (@PrePersist):


                @PrePersist
                public void prePersist(Object entity) {
                    if (entity instanceof Address) {
                     Address address = (Address)entity;
                     String type = address.getClass().getSimpleName();
                     address.setType(type);
                         }
                  }
                



                Also this hql will work as well:


                select objA 
                from classA objA , subclassB objB
                where objA.xxx = objB.yyy 
                



                Regards.


                Roger.