-->
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.  [ 2 posts ] 
Author Message
 Post subject: Lazy loading a non-PK based 1-to-1 relationship
PostPosted: Fri Sep 07, 2007 9:02 am 
Newbie

Joined: Wed Mar 14, 2007 12:08 pm
Posts: 3
I am using Hibernate 3.2.2 against Oracle 10g and have a problem with one particular type of relationship, a one-to-one where the link is on some arbitrary (i.e. not the primary key) columns. I need to make this sort of join as there are multiple possible ways in which 2 tables can be joined together. An example follows

Code:
    <class name="LocalInstrumentImpl"
           table="INSTRUMENT_FOR_RESYNC"
           entity-name="LocalInstrumentSearch"
           proxy="LocalInstrument"
           mutable="false">
.
.
.
        <one-to-one name="foreignSiblingViaIsin"
                    entity-name="ForeignInstrumentSearch"
                    lazy="proxy"
                    fetch="select"
                    access="field"
                    property-ref="isin"
                    constrained="true">
            <formula>isin</formula>
        </one-to-one>
.
.
.
.
        <query name="newLocalInstrument"
               cacheable="false">
           select ins
           from ForeignInstrumentSearch ins
           where
                not exists (from LocalInstrumentSearch local where local.isin = ins.isin)
            and not exists (from LocalInstrumentSearch cov where local.gedmId = ins.coverageId)
        </query>
    </class>


If I execute the newLocalInstrument query then I will see the following statements issued in my log demonstrating that it is eagerly fetching the foreignSiblingViaIsin property (and obviously finding nothing as we know in this instance there won't be a match).

Code:
07 Sep 2007 13:46:31,231 DEBUG [org.hibernate.SQL:393] (main:) - /* named HQL query ForeignInstrumentSearch.newLocalInstrument */ .... my query.....
07 Sep 2007 13:46:31,949 DEBUG [org.hibernate.SQL:393] (main:) - /* load CoverageInstrumentSearch */ ..... query to load by ISIN .....


I've stripped off the actual SQL generated as it's v long and not relevant to this issue.

As far as I can see in the code the association is loaded from the database and then proxied because the association is not on the primary. The offending code is called from org.hibernate.engine.TwoPhaseLoad (line 116)

Code:
      for ( int i = 0; i < hydratedState.length; i++ ) {
         final Object value = hydratedState[i];
         if ( value!=LazyPropertyInitializer.UNFETCHED_PROPERTY && value!=BackrefPropertyAccessor.UNKNOWN ) {
            hydratedState[i] = types[i].resolve( value, session, entity ); // this is line 116
         }
      }


in this case types[i] will be an instance of org.hibernate.type.SpecialOneToOneType and resolve is provided by its base class org.hibernate.type.EntityType, the method is repeated below

Code:
   public Object resolve(Object value, SessionImplementor session, Object owner) throws HibernateException {
      if ( isNotEmbedded( session ) ) {
         return value;
      }

      if ( value == null ) {
         return null;
      }
      else {
         if ( isNull( owner, session ) ) {
            return null; //EARLY EXIT!
         }

         if ( isReferenceToPrimaryKey() ) {
            return resolveIdentifier( (Serializable) value, session );
         }
         else {
            return loadByUniqueKey( getAssociatedEntityName(), uniqueKeyPropertyName, value, session );
         }
      }
   }


hence loadByUniqueKey is called, the database gets hit and then the instance is proxied.

I have a couple of questions on this;

1. is it possible to avoid an eager fetch of this type of relationship? if so, what I am doing wrong?
2. if it is not possible, is there a technical reason why this can't be implemented or is it on the feature list?

I'm dealing with ~600k records in this specific query and have two such relationships on this type hence it would be nice if I could avoid the additional 1.2m trips to the database this will trigger! At present my only solution is to replace the one-to-one with a set and assume in code that there will only ever be 1 instance in the set. This is obviously very crufty but will/should work.

Cheers
Matt


Top
 Profile  
 
 Post subject:
PostPosted: Mon Sep 10, 2007 6:46 am 
Newbie

Joined: Wed Mar 14, 2007 12:08 pm
Posts: 3
anyone?


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

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.