ibatis-user-java mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Wouter Roose <wouter.ro...@guest.minfin.fed.be>
Subject RE: Lazy loading issues
Date Mon, 26 Mar 2007 10:38:56 GMT
Ok Thanks for the feedback

 

Our first implementation based on this solution seems to work

 

 

Wouter

 

  _____  

Van: MCCORMICK, Paul [mailto:Paul.McCORMICK@doir.wa.gov.au] 
Verzonden: maandag 19 maart 2007 3:02
Aan: user-java@ibatis.apache.org
Onderwerp: RE: Lazy loading issues

 

I'll give you some of the sudo code that I used to overcome lazy loading of
1 to 1 relationships.  I had to write extra code to allow lazy loaded
objects to be serializable and cloneable.  The code has nothing to do with
lazy loading of lists. 

 

All objects loaded from the database implement the IBaseDomain interface.  

 

interface IBaseDomain {

    Integer id              // The primary key which is never null

    Integer versionId  // Used of optomistic locking

    boolean setNewCalled // Used when the id and versionId have been set to
null by client code.

}

 

 

Here is the ResultObjectFactory used.  Quite simple,  just enhances anything
that implements IBaseDomain.

public final class EmitsResultObjectFactory implements ResultObjectFactory {

 

    public final Object createInstance(String arg0, Class clazz) throws
InstantiationException, IllegalAccessException {
    
        if (IBaseDomain.class.isAssignableFrom(clazz)) {           
            Enhancer enhancer = new Enhancer();
            enhancer.setSuperclass(clazz);
 
enhancer.setCallbackFilter(EnhancedBaseDomainCallbackFilter.instance);
 
enhancer.setCallbacks(EnhancedBaseDomainCallbackFilter.callbacks);
            return enhancer.create();
        } else {
            return null;
        }

 

    }

 

    public void setProperty(String arg0, String arg1) {}

}

 

 

-----------------------------------------------------------


public final class EnhancedBaseDomainCallbackFilter implements
CallbackFilter, MethodInterceptor, Serializable {

 

    private EnhancedBaseDomainCallbackFilter() {

 

    }

 

    public static final EnhancedBaseDomainCallbackFilter instance = new
EnhancedBaseDomainCallbackFilter();

 

    public static final Callback[] callbacks = { NoOpCallback.INSTANCE,
instance };

 

    public final int accept(Method method) {

 

        if (method.getName().startsWith("get") &&
method.getParameterTypes().length == 0 &&
IBaseDomain.class.isAssignableFrom(method.getReturnType())) {
            return 1; // BaseDomain return types are intercepted.
        }
        return 0; // the No operation interceptor. Does nothing.
    }

 

    /**
     * Allows using the enhancementEnabled ibatis option. This option allows
the lazy loading of single objects ( and not just Lists ).
     * 
     * e.g the following method can be lazy loaded: public Party getParty();
     * 
     * A problem occurs if calling the "public Party getParty()" should
return null. Instead of null being returned a 'wrapped null' is returned.
This MethodInterceptor fixes this
     * feature/bug.
     */
    public final Object intercept(final Object object, final Method method,
final Object[] args, final MethodProxy proxy) throws Throwable {

 

        Object obj = proxy.invokeSuper(object, args);
        if ((obj == null) || (!(obj instanceof IBaseDomain))) {
            return obj;
        }

 

        IBaseDomain baseDomain = (IBaseDomain) obj;
        
        // All Enhanced objects implement Factory.
        if (baseDomain instanceof Factory) {

            // If the primary key is null then the object is null unless the
client code called setNew()
            if (baseDomain.getId() == null) {
                try {
                    // If baseDomain.setNew() is called then the object is
valid.  If not then its a return null instead of the proxy.
                    if (!baseDomain.isSetNewCalled()) {
                        return null;
                    }
                // There is a bug in cg lib that can cause a Null Pointer to
be thrown on a cloned enhanced object.  Don't know why but this is a temp
fix.
                } catch (NullPointerException e) {
                    Log log =
LogFactory.getLog(EnhancedBaseDomainCallbackFilter.class);

                    log.debug("EnhancedBaseDomainCallbackFilter.intercept
caught NullPointerException on method " + method.getName() + " object:" +
baseDomain.getClass().getName());
                    return null;
                }
            }
        }
        
        return baseDomain;

 

    }

 

    private interface NoOpCallback extends NoOp, Serializable {
        /**
         * A thread-safe singleton instance of the <code>NoOpCallback</code>
callback.
         */
        public static final NoOpCallback INSTANCE = new NoOpCallback() {
        };
    }

 

}


-----------------------------------------------------------

I changed the Ibatis class EnhancedLazyResultLoader. 

1) I had to make an inner class Serializable.  This involved making the
field that links to the jdbc connection transient.  I then had to put my
application code into this class to set this transient field.  Thats a hack
that you may want to improve on.

 

2) Changed the EnhancedLazyResultLoaderImpl.loadResult() method to only
create proxy objects for IBaseDomain results ( that are not abstract).  The
reason for not lazy loading abstract classes is because the instanceof does
not work as expected when comparing to a concrete class.

Here is the method code.  I'll attach a file of the whole class also but
most of it is not relevent.

    public Object loadResult() throws SQLException {
      if (...)

            ....
      } else if (Collection.class.isAssignableFrom(targetType)) {
       .....

        // This is my custom code for lazy loading 1 to 1 relationships.  
      } else if ( IBaseDomain.class.isAssignableFrom(targetType)  &&
!Modifier.isAbstract(targetType.getModifiers())) {
          return  Enhancer.create(targetType, new Class[] {
IBaseDomain.class } , this);
      } else {
     loadObject();
  return resultObject;
      }
    }

 

I hope this helps,

Paul

 

 

  _____  

From: Wouter Roose [mailto:wouter.roose@guest.minfin.fed.be] 
Sent: Friday, 16 March 2007 6:13 PM
To: user-java@ibatis.apache.org
Subject: RE: Lazy loading issues

Anybody?

 

  _____  

Van: Wouter Roose [mailto:wouter.roose@guest.minfin.fed.be] 
Verzonden: maandag 12 maart 2007 8:49
Aan: user-java@ibatis.apache.org
Onderwerp: Lazy loading issues

 

Hello

 

Concerning

 
<http://opensource.atlassian.com/confluence/oss/display/IBATIS/Lazy+loading+
issues>
http://opensource.atlassian.com/confluence/oss/display/IBATIS/Lazy+loading+i
ssues

 

I encountered the second problem. Could somebody be so kind to add some
coding examples to the solution on the wiki? especially the one with the
ResultObjectFactory. As I'm not an expert iBATIS developer it is difficult
to implement this solution based on this explanation
 
Regards,
Wouter

 

 

  _____  

Disclaimer <http://www.minfin.fgov.be/disclaimer.htm> 

  _____  

Disclaimer <http://www.minfin.fgov.be/disclaimer.htm> 

"DISCLAIMER: This email, including any attachments, is intended only for use
by the addressee(s) and may contain confidential and/or personal information
and may also be the subject of legal privilege. If you are not the intended
recipient, you must not disclose or use the information contained in it. In
this case, please let me know by return email, delete the message
permanently from your system and destroy any copies. 

Before you take any action based upon advice and/or information contained in
this email you should carefully consider the advice and information and
consider obtaining relevant independent advice.
	


----------------------------------------------------------------
- Disclaimer: http://www.minfin.fgov.be/disclaimer.htm

Mime
View raw message