You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ibatis.apache.org by cb...@apache.org on 2010/02/13 04:01:45 UTC

svn commit: r909700 - in /ibatis/java/ibatis-3/trunk: ./ doc/en/ ibatis-3-core/src/main/java/org/apache/ibatis/builder/xml/ ibatis-3-core/src/main/java/org/apache/ibatis/executor/loader/ ibatis-3-core/src/main/java/org/apache/ibatis/executor/resultset/...

Author: cbegin
Date: Sat Feb 13 03:01:44 2010
New Revision: 909700

URL: http://svn.apache.org/viewvc?rev=909700&view=rev
Log:
Fixed IBATIS-737 lazy loading problem

Added:
    ibatis/java/ibatis-3/trunk/ibatis-3-core/src/main/java/org/apache/ibatis/executor/loader/ResultLoaderMap.java
      - copied, changed from r901055, ibatis/java/ibatis-3/trunk/ibatis-3-core/src/main/java/org/apache/ibatis/executor/loader/ResultLoaderRegistry.java
Removed:
    ibatis/java/ibatis-3/trunk/ibatis-3-core/src/main/java/org/apache/ibatis/executor/loader/ResultLoaderRegistry.java
Modified:
    ibatis/java/ibatis-3/trunk/doc/en/iBATIS-3-User-Guide.doc
    ibatis/java/ibatis-3/trunk/doc/en/iBATIS-3-User-Guide.pdf
    ibatis/java/ibatis-3/trunk/ibatis-3-core/src/main/java/org/apache/ibatis/builder/xml/XMLConfigBuilder.java
    ibatis/java/ibatis-3/trunk/ibatis-3-core/src/main/java/org/apache/ibatis/executor/loader/ResultLoader.java
    ibatis/java/ibatis-3/trunk/ibatis-3-core/src/main/java/org/apache/ibatis/executor/loader/ResultObjectProxy.java
    ibatis/java/ibatis-3/trunk/ibatis-3-core/src/main/java/org/apache/ibatis/executor/resultset/FastResultSetHandler.java
    ibatis/java/ibatis-3/trunk/ibatis-3-core/src/main/java/org/apache/ibatis/executor/resultset/NestedResultSetHandler.java
    ibatis/java/ibatis-3/trunk/ibatis-3-core/src/main/java/org/apache/ibatis/session/Configuration.java
    ibatis/java/ibatis-3/trunk/ibatis-3-core/src/test/java/org/apache/ibatis/executor/SerializableProxyTest.java
    ibatis/java/ibatis-3/trunk/ibatis-3-core/src/test/java/org/apache/ibatis/submitted/cglib_lazy_error/CglibNPELazyTest.java
    ibatis/java/ibatis-3/trunk/ibatis-3-core/src/test/java/org/apache/ibatis/submitted/cglib_lazy_error/CglibNPETest.java
    ibatis/java/ibatis-3/trunk/ibatis-3-core/src/test/java/org/apache/ibatis/submitted/cglib_lazy_error/CreateDB.sql
    ibatis/java/ibatis-3/trunk/ibatis-3-core/src/test/java/org/apache/ibatis/submitted/cglib_lazy_error/Person.java
    ibatis/java/ibatis-3/trunk/ibatis-3-core/src/test/java/org/apache/ibatis/submitted/cglib_lazy_error/Person.xml
    ibatis/java/ibatis-3/trunk/ibatis-3-core/src/test/java/org/apache/ibatis/submitted/cglib_lazy_error/PersonMapper.java
    ibatis/java/ibatis-3/trunk/ibatis-3-core/src/test/java/org/apache/ibatis/submitted/cglib_lazy_error/ibatisConfig.xml
    ibatis/java/ibatis-3/trunk/ibatis-3-core/src/test/java/org/apache/ibatis/submitted/cglib_lazy_error/ibatisConfigLazy.xml
    ibatis/java/ibatis-3/trunk/version.properties

Modified: ibatis/java/ibatis-3/trunk/doc/en/iBATIS-3-User-Guide.doc
URL: http://svn.apache.org/viewvc/ibatis/java/ibatis-3/trunk/doc/en/iBATIS-3-User-Guide.doc?rev=909700&r1=909699&r2=909700&view=diff
==============================================================================
Binary files - no diff available.

Modified: ibatis/java/ibatis-3/trunk/doc/en/iBATIS-3-User-Guide.pdf
URL: http://svn.apache.org/viewvc/ibatis/java/ibatis-3/trunk/doc/en/iBATIS-3-User-Guide.pdf?rev=909700&r1=909699&r2=909700&view=diff
==============================================================================
Binary files - no diff available.

Modified: ibatis/java/ibatis-3/trunk/ibatis-3-core/src/main/java/org/apache/ibatis/builder/xml/XMLConfigBuilder.java
URL: http://svn.apache.org/viewvc/ibatis/java/ibatis-3/trunk/ibatis-3-core/src/main/java/org/apache/ibatis/builder/xml/XMLConfigBuilder.java?rev=909700&r1=909699&r2=909700&view=diff
==============================================================================
--- ibatis/java/ibatis-3/trunk/ibatis-3-core/src/main/java/org/apache/ibatis/builder/xml/XMLConfigBuilder.java (original)
+++ ibatis/java/ibatis-3/trunk/ibatis-3-core/src/main/java/org/apache/ibatis/builder/xml/XMLConfigBuilder.java Sat Feb 13 03:01:44 2010
@@ -156,7 +156,8 @@
       }
       configuration.setAutoMappingBehavior(AutoMappingBehavior.valueOf(stringValueOf(props.getProperty("autoMappingBehavior"), "PARTIAL")));
       configuration.setCacheEnabled(booleanValueOf(props.getProperty("cacheEnabled"), true));
-      configuration.setLazyLoadingEnabled(booleanValueOf(props.getProperty("lazyLoadingEnabled"), false));
+      configuration.setLazyLoadingEnabled(booleanValueOf(props.getProperty("lazyLoadingEnabled"), safeCglibCheck()));
+      configuration.setAggressiveLazyLoading(booleanValueOf(props.getProperty("aggressiveLazyLoading"), true));
       configuration.setMultipleResultSetsEnabled(booleanValueOf(props.getProperty("multipleResultSetsEnabled"), true));
       configuration.setUseColumnLabel(booleanValueOf(props.getProperty("useColumnLabel"), true));
       configuration.setUseGeneratedKeys(booleanValueOf(props.getProperty("useGeneratedKeys"), false));
@@ -165,6 +166,14 @@
     }
   }
 
+  private boolean safeCglibCheck() {
+    try {
+      return Resources.classForName("net.sf.cglib.proxy.Enhancer") != null;
+    } catch (Exception e) {
+      return false;
+    }
+  }
+
   private void environmentsElement(XNode context) throws Exception {
     if (context != null) {
       if (environment == null) {

Modified: ibatis/java/ibatis-3/trunk/ibatis-3-core/src/main/java/org/apache/ibatis/executor/loader/ResultLoader.java
URL: http://svn.apache.org/viewvc/ibatis/java/ibatis-3/trunk/ibatis-3-core/src/main/java/org/apache/ibatis/executor/loader/ResultLoader.java?rev=909700&r1=909699&r2=909700&view=diff
==============================================================================
--- ibatis/java/ibatis-3/trunk/ibatis-3-core/src/main/java/org/apache/ibatis/executor/loader/ResultLoader.java (original)
+++ ibatis/java/ibatis-3/trunk/ibatis-3-core/src/main/java/org/apache/ibatis/executor/loader/ResultLoader.java Sat Feb 13 03:01:44 2010
@@ -11,7 +11,6 @@
 import org.apache.ibatis.session.ExecutorType;
 import org.apache.ibatis.session.RowBounds;
 import org.apache.ibatis.transaction.Transaction;
-import org.apache.ibatis.transaction.TransactionFactory;
 import org.apache.ibatis.transaction.jdbc.JdbcTransaction;
 
 import javax.sql.DataSource;

Copied: ibatis/java/ibatis-3/trunk/ibatis-3-core/src/main/java/org/apache/ibatis/executor/loader/ResultLoaderMap.java (from r901055, ibatis/java/ibatis-3/trunk/ibatis-3-core/src/main/java/org/apache/ibatis/executor/loader/ResultLoaderRegistry.java)
URL: http://svn.apache.org/viewvc/ibatis/java/ibatis-3/trunk/ibatis-3-core/src/main/java/org/apache/ibatis/executor/loader/ResultLoaderMap.java?p2=ibatis/java/ibatis-3/trunk/ibatis-3-core/src/main/java/org/apache/ibatis/executor/loader/ResultLoaderMap.java&p1=ibatis/java/ibatis-3/trunk/ibatis-3-core/src/main/java/org/apache/ibatis/executor/loader/ResultLoaderRegistry.java&r1=901055&r2=909700&rev=909700&view=diff
==============================================================================
--- ibatis/java/ibatis-3/trunk/ibatis-3-core/src/main/java/org/apache/ibatis/executor/loader/ResultLoaderRegistry.java (original)
+++ ibatis/java/ibatis-3/trunk/ibatis-3-core/src/main/java/org/apache/ibatis/executor/loader/ResultLoaderMap.java Sat Feb 13 03:01:44 2010
@@ -6,36 +6,40 @@
 import java.sql.SQLException;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.Set;
 
-public class ResultLoaderRegistry implements Serializable {
+public class ResultLoaderMap implements Serializable {
 
   private final Map<String, LoadPair> loaderMap = new HashMap<String, LoadPair>();
 
-  public void registerLoader(String property, MetaObject metaResultObject, ResultLoader resultLoader) {
-    // Converts property to method name strictly for performance.
+  public void addLoader(String property, MetaObject metaResultObject, ResultLoader resultLoader) {
     String upperFirst = getUppercaseFirstProperty(property);
-    loaderMap.put(toGetter(upperFirst), new LoadPair(property, metaResultObject, resultLoader));
-    loaderMap.put(toSetter(upperFirst), new LoadPair(property, metaResultObject, resultLoader));
+    loaderMap.put(upperFirst, new LoadPair(property, metaResultObject, resultLoader));
   }
 
-  public void loadAll() throws SQLException {
-      synchronized (loaderMap) {
-        Object[] keys = loaderMap.keySet().toArray();
-        for (Object key : keys) {
-          LoadPair pair = loaderMap.remove(key);
-          if (pair != null) {
-            pair.load();
-          }
-        }
-      }
-    }
+  public int size() throws SQLException {
+    return loaderMap.size();
+  }
+
+  public boolean hasLoader(String methodName) throws SQLException {
+    return loaderMap.containsKey(methodName.toUpperCase());
+  }
 
-  private String toGetter(String first) {
-    return "GET" + first;
+  public boolean load(String property) throws SQLException {
+    LoadPair pair = loaderMap.remove(property.toUpperCase());
+    if (pair != null) {
+      pair.load();
+      return true;
+    }
+    return false;
   }
 
-  private String toSetter(String first) {
-    return "SET" + first;
+  public void loadAll() throws SQLException {
+    final Set<String> methodNameSet = loaderMap.keySet();
+    String[] methodNames = methodNameSet.toArray(new String[methodNameSet.size()]);
+    for (String methodName : methodNames) {
+      load(methodName);
+    }
   }
 
   private static String getUppercaseFirstProperty(String property) {
@@ -43,7 +47,7 @@
     return parts[0].toUpperCase();
   }
 
-  private class LoadPair {
+  private static class LoadPair {
     private String property;
     private MetaObject metaResultObject;
     private ResultLoader resultLoader;

Modified: ibatis/java/ibatis-3/trunk/ibatis-3-core/src/main/java/org/apache/ibatis/executor/loader/ResultObjectProxy.java
URL: http://svn.apache.org/viewvc/ibatis/java/ibatis-3/trunk/ibatis-3-core/src/main/java/org/apache/ibatis/executor/loader/ResultObjectProxy.java?rev=909700&r1=909699&r2=909700&view=diff
==============================================================================
--- ibatis/java/ibatis-3/trunk/ibatis-3-core/src/main/java/org/apache/ibatis/executor/loader/ResultObjectProxy.java (original)
+++ ibatis/java/ibatis-3/trunk/ibatis-3-core/src/main/java/org/apache/ibatis/executor/loader/ResultObjectProxy.java Sat Feb 13 03:01:44 2010
@@ -1,50 +1,84 @@
 package org.apache.ibatis.executor.loader;
 
 import net.sf.cglib.proxy.Enhancer;
-import net.sf.cglib.proxy.InvocationHandler;
+import net.sf.cglib.proxy.MethodInterceptor;
+import net.sf.cglib.proxy.MethodProxy;
 import org.apache.ibatis.reflection.ExceptionUtil;
 import org.apache.ibatis.reflection.property.PropertyNamer;
 import org.apache.ibatis.type.TypeHandlerRegistry;
 
 import java.io.Serializable;
 import java.lang.reflect.Method;
+import java.lang.reflect.Field;
+import java.util.*;
 
 public class ResultObjectProxy {
 
+  private static final Set<String> objectMethods = new HashSet<String>(Arrays.asList(new String[]{"equals","hashCode","toString"}));
   private static final TypeHandlerRegistry registry = new TypeHandlerRegistry();
 
-  public static Object createProxy(Class type, Object target, ResultLoaderRegistry lazyLoader) {
-    return EnhancedResultObjectProxyImpl.createProxy(type, target, lazyLoader);
+  public static Object createProxy(Object target, ResultLoaderMap lazyLoader, boolean aggressive) {
+    return EnhancedResultObjectProxyImpl.createProxy(target, lazyLoader, aggressive);
   }
 
-  private static class EnhancedResultObjectProxyImpl implements InvocationHandler, Serializable {
+  private static class EnhancedResultObjectProxyImpl implements MethodInterceptor, Serializable {
 
-    private Object target;
-    private ResultLoaderRegistry lazyLoader;
+    private ResultLoaderMap lazyLoader;
+    private boolean aggressive;
 
-    private EnhancedResultObjectProxyImpl(Object target, ResultLoaderRegistry lazyLoader) {
-      this.target = target;
+    private EnhancedResultObjectProxyImpl(ResultLoaderMap lazyLoader, boolean aggressive) {
       this.lazyLoader = lazyLoader;
+      this.aggressive = aggressive;
     }
 
-    public static Object createProxy(Class type, Object target, ResultLoaderRegistry lazyLoader) {
+    public static Object createProxy(Object target, ResultLoaderMap lazyLoader, boolean aggressive) {
+      Class type = target.getClass();
       if (registry.hasTypeHandler(type)) {
         return target;
       } else {
-        return Enhancer.create(type, new EnhancedResultObjectProxyImpl(target, lazyLoader));
+        final Object enhanced = Enhancer.create(target.getClass(), new EnhancedResultObjectProxyImpl(lazyLoader, aggressive));
+        copyInitialState(type, target, enhanced);
+        return enhanced;
       }
     }
 
-    public Object invoke(Object o, Method method, Object[] args) throws Throwable {
+    public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
       try {
-        if (!Object.class.equals(method.getDeclaringClass()) && PropertyNamer.isGetter(method.getName())) {
-            lazyLoader.loadAll();
+        final String methodName = method.getName();
+        synchronized (lazyLoader) {
+          if (lazyLoader.size() > 0) {
+            if (aggressive || objectMethods.contains(methodName)) {
+              lazyLoader.loadAll();
+            } else if (PropertyNamer.isProperty(methodName)) {
+              final String property = PropertyNamer.methodToProperty(methodName);
+              if (lazyLoader.hasLoader(property)) {
+                lazyLoader.load(property);
+              }
+            }
+          }
         }
-        return method.invoke(target, args);
+        return methodProxy.invokeSuper(o, args);
       } catch (Throwable t) {
         throw ExceptionUtil.unwrapThrowable(t);
       }
     }
+
+    private static void copyInitialState(Class type, Object target, Object enhanced) {
+      Class parent = type;
+      while (parent != null) {
+        final Field[] fields = parent.getDeclaredFields();
+        for(Field field : fields) {
+          try {
+            field.setAccessible(true);
+            field.set(enhanced,field.get(target));
+          } catch (Exception e) {
+            // Nothing useful to do, will only fail on final fields, which will be ignored.
+          }
+        }
+        parent = parent.getSuperclass();
+      }
+    }
+
   }
 
 }

Modified: ibatis/java/ibatis-3/trunk/ibatis-3-core/src/main/java/org/apache/ibatis/executor/resultset/FastResultSetHandler.java
URL: http://svn.apache.org/viewvc/ibatis/java/ibatis-3/trunk/ibatis-3-core/src/main/java/org/apache/ibatis/executor/resultset/FastResultSetHandler.java?rev=909700&r1=909699&r2=909700&view=diff
==============================================================================
--- ibatis/java/ibatis-3/trunk/ibatis-3-core/src/main/java/org/apache/ibatis/executor/resultset/FastResultSetHandler.java (original)
+++ ibatis/java/ibatis-3/trunk/ibatis-3-core/src/main/java/org/apache/ibatis/executor/resultset/FastResultSetHandler.java Sat Feb 13 03:01:44 2010
@@ -4,7 +4,7 @@
 import org.apache.ibatis.executor.Executor;
 import org.apache.ibatis.executor.ExecutorException;
 import org.apache.ibatis.executor.loader.ResultLoader;
-import org.apache.ibatis.executor.loader.ResultLoaderRegistry;
+import org.apache.ibatis.executor.loader.ResultLoaderMap;
 import org.apache.ibatis.executor.loader.ResultObjectProxy;
 import org.apache.ibatis.executor.parameter.ParameterHandler;
 import org.apache.ibatis.executor.result.DefaultResultContext;
@@ -166,7 +166,7 @@
   protected Object getRowValue(ResultSet rs, ResultMap resultMap, CacheKey rowKey) throws SQLException {
     final List<String> mappedColumnNames = new ArrayList<String>();
     final List<String> unmappedColumnNames = new ArrayList<String>();
-    final ResultLoaderRegistry lazyLoader = instantiateResultLoaderRegistry();
+    final ResultLoaderMap lazyLoader = instantiateResultLoaderMap();
     Object resultObject = createResultObject(rs, resultMap, lazyLoader);
     if (resultObject != null && !typeHandlerRegistry.hasTypeHandler(resultMap.getType())) {
       final MetaObject metaObject = configuration.newMetaObject(resultObject);
@@ -182,9 +182,9 @@
     return resultObject;
   }
 
-  protected ResultLoaderRegistry instantiateResultLoaderRegistry() {
+  protected ResultLoaderMap instantiateResultLoaderMap() {
     if (configuration.isLazyLoadingEnabled()) {
-      return new ResultLoaderRegistry();
+      return new ResultLoaderMap();
     } else {
       return null;
     }
@@ -194,7 +194,7 @@
   // PROPERTY MAPPINGS
   //
 
-  protected boolean applyPropertyMappings(ResultSet rs, ResultMap resultMap, List<String> mappedColumnNames, MetaObject metaObject, ResultLoaderRegistry lazyLoader) throws SQLException {
+  protected boolean applyPropertyMappings(ResultSet rs, ResultMap resultMap, List<String> mappedColumnNames, MetaObject metaObject, ResultLoaderMap lazyLoader) throws SQLException {
     boolean foundValues = false;
     final List<ResultMapping> propertyMappings = resultMap.getPropertyResultMappings();
     for (ResultMapping propertyMapping : propertyMappings) {
@@ -211,7 +211,7 @@
     return foundValues;
   }
 
-  protected Object getPropertyMappingValue(ResultSet rs, MetaObject metaResultObject, ResultMapping propertyMapping, ResultLoaderRegistry lazyLoader) throws SQLException {
+  protected Object getPropertyMappingValue(ResultSet rs, MetaObject metaResultObject, ResultMapping propertyMapping, ResultLoaderMap lazyLoader) throws SQLException {
     final TypeHandler typeHandler = propertyMapping.getTypeHandler();
     if (propertyMapping.getNestedQueryId() != null) {
       return getNestedQueryMappingValue(rs, metaResultObject, propertyMapping, lazyLoader);
@@ -264,10 +264,10 @@
   // INSTANTIATION & CONSTRUCTOR MAPPING
   //
 
-  protected Object createResultObject(ResultSet rs, ResultMap resultMap, ResultLoaderRegistry lazyLoader) throws SQLException {
+  protected Object createResultObject(ResultSet rs, ResultMap resultMap, ResultLoaderMap lazyLoader) throws SQLException {
     final Object resultObject = createResultObject(rs, resultMap);
     if (resultObject != null && configuration.isLazyLoadingEnabled()) {
-      return ResultObjectProxy.createProxy(resultMap.getType(), resultObject, lazyLoader);
+      return ResultObjectProxy.createProxy(resultObject, lazyLoader, configuration.isAggressiveLazyLoading());
     }
     return resultObject;
   }
@@ -319,7 +319,7 @@
   // NESTED QUERY
   //
 
-  protected Object getNestedQueryMappingValue(ResultSet rs, MetaObject metaResultObject, ResultMapping propertyMapping, ResultLoaderRegistry lazyLoader) throws SQLException {
+  protected Object getNestedQueryMappingValue(ResultSet rs, MetaObject metaResultObject, ResultMapping propertyMapping, ResultLoaderMap lazyLoader) throws SQLException {
     final String nestedQueryId = propertyMapping.getNestedQueryId();
     final String property = propertyMapping.getProperty();
     final MappedStatement nestedQuery = configuration.getMappedStatement(nestedQueryId);
@@ -333,7 +333,7 @@
       } else {
         final ResultLoader resultLoader = new ResultLoader(configuration, executor, nestedQuery, nestedQueryParameterObject, propertyMapping.getJavaType());
         if (configuration.isLazyLoadingEnabled()) {
-          lazyLoader.registerLoader(property, metaResultObject, resultLoader);
+          lazyLoader.addLoader(property, metaResultObject, resultLoader);
         } else {
           value = resultLoader.loadResult();
         }

Modified: ibatis/java/ibatis-3/trunk/ibatis-3-core/src/main/java/org/apache/ibatis/executor/resultset/NestedResultSetHandler.java
URL: http://svn.apache.org/viewvc/ibatis/java/ibatis-3/trunk/ibatis-3-core/src/main/java/org/apache/ibatis/executor/resultset/NestedResultSetHandler.java?rev=909700&r1=909699&r2=909700&view=diff
==============================================================================
--- ibatis/java/ibatis-3/trunk/ibatis-3-core/src/main/java/org/apache/ibatis/executor/resultset/NestedResultSetHandler.java (original)
+++ ibatis/java/ibatis-3/trunk/ibatis-3-core/src/main/java/org/apache/ibatis/executor/resultset/NestedResultSetHandler.java Sat Feb 13 03:01:44 2010
@@ -3,7 +3,7 @@
 import org.apache.ibatis.cache.CacheKey;
 import org.apache.ibatis.executor.Executor;
 import org.apache.ibatis.executor.ExecutorException;
-import org.apache.ibatis.executor.loader.ResultLoaderRegistry;
+import org.apache.ibatis.executor.loader.ResultLoaderMap;
 import org.apache.ibatis.executor.parameter.ParameterHandler;
 import org.apache.ibatis.executor.result.DefaultResultContext;
 import org.apache.ibatis.mapping.BoundSql;
@@ -94,7 +94,7 @@
     } else {
       final List<String> mappedColumnNames = new ArrayList<String>();
       final List<String> unmappedColumnNames = new ArrayList<String>();
-      final ResultLoaderRegistry lazyLoader = instantiateResultLoaderRegistry();
+      final ResultLoaderMap lazyLoader = instantiateResultLoaderMap();
       Object resultObject = createResultObject(rs, resultMap, lazyLoader);
       if (resultObject != null && !typeHandlerRegistry.hasTypeHandler(resultMap.getType())) {
         final MetaObject metaObject = configuration.newMetaObject(resultObject);

Modified: ibatis/java/ibatis-3/trunk/ibatis-3-core/src/main/java/org/apache/ibatis/session/Configuration.java
URL: http://svn.apache.org/viewvc/ibatis/java/ibatis-3/trunk/ibatis-3-core/src/main/java/org/apache/ibatis/session/Configuration.java?rev=909700&r1=909699&r2=909700&view=diff
==============================================================================
--- ibatis/java/ibatis-3/trunk/ibatis-3-core/src/main/java/org/apache/ibatis/session/Configuration.java (original)
+++ ibatis/java/ibatis-3/trunk/ibatis-3-core/src/main/java/org/apache/ibatis/session/Configuration.java Sat Feb 13 03:01:44 2010
@@ -40,6 +40,7 @@
   protected Environment environment;
 
   protected boolean lazyLoadingEnabled = false;
+  protected boolean aggressiveLazyLoading = true;
   protected boolean multipleResultSetsEnabled = true;
   protected boolean useGeneratedKeys = false;
   protected boolean useColumnLabel = true;
@@ -115,6 +116,14 @@
     this.lazyLoadingEnabled = lazyLoadingEnabled;
   }
 
+  public boolean isAggressiveLazyLoading() {
+    return aggressiveLazyLoading;
+  }
+
+  public void setAggressiveLazyLoading(boolean aggressiveLazyLoading) {
+    this.aggressiveLazyLoading = aggressiveLazyLoading;
+  }
+
   public boolean isMultipleResultSetsEnabled() {
     return multipleResultSetsEnabled;
   }

Modified: ibatis/java/ibatis-3/trunk/ibatis-3-core/src/test/java/org/apache/ibatis/executor/SerializableProxyTest.java
URL: http://svn.apache.org/viewvc/ibatis/java/ibatis-3/trunk/ibatis-3-core/src/test/java/org/apache/ibatis/executor/SerializableProxyTest.java?rev=909700&r1=909699&r2=909700&view=diff
==============================================================================
--- ibatis/java/ibatis-3/trunk/ibatis-3-core/src/test/java/org/apache/ibatis/executor/SerializableProxyTest.java (original)
+++ ibatis/java/ibatis-3/trunk/ibatis-3-core/src/test/java/org/apache/ibatis/executor/SerializableProxyTest.java Sat Feb 13 03:01:44 2010
@@ -2,7 +2,7 @@
 
 import domain.blog.Author;
 import domain.blog.Section;
-import org.apache.ibatis.executor.loader.ResultLoaderRegistry;
+import org.apache.ibatis.executor.loader.ResultLoaderMap;
 import org.apache.ibatis.executor.loader.ResultObjectProxy;
 import static org.junit.Assert.assertEquals;
 import org.junit.Test;
@@ -14,7 +14,7 @@
   @Test
   public void shouldDemonstrateSerializableEnhancer() throws Exception {
     Author author = new Author(999, "someone", "!@#@!#!@#", "someone@somewhere.com", "blah", Section.NEWS);
-    Object proxy = ResultObjectProxy.createProxy(Author.class, author, new ResultLoaderRegistry());
+    Object proxy = ResultObjectProxy.createProxy(author, new ResultLoaderMap(), true);
     byte[] bytes = serialize((Serializable) proxy);
     Object proxy2 = deserialize(bytes);
     assertEquals(author.toString(), proxy2.toString());

Modified: ibatis/java/ibatis-3/trunk/ibatis-3-core/src/test/java/org/apache/ibatis/submitted/cglib_lazy_error/CglibNPELazyTest.java
URL: http://svn.apache.org/viewvc/ibatis/java/ibatis-3/trunk/ibatis-3-core/src/test/java/org/apache/ibatis/submitted/cglib_lazy_error/CglibNPELazyTest.java?rev=909700&r1=909699&r2=909700&view=diff
==============================================================================
--- ibatis/java/ibatis-3/trunk/ibatis-3-core/src/test/java/org/apache/ibatis/submitted/cglib_lazy_error/CglibNPELazyTest.java (original)
+++ ibatis/java/ibatis-3/trunk/ibatis-3-core/src/test/java/org/apache/ibatis/submitted/cglib_lazy_error/CglibNPELazyTest.java Sat Feb 13 03:01:44 2010
@@ -1,10 +1,5 @@
 package org.apache.ibatis.submitted.cglib_lazy_error;
 
-import java.io.PrintWriter;
-import java.io.Reader;
-import java.sql.Connection;
-import java.sql.DriverManager;
-
 import org.apache.ibatis.io.Resources;
 import org.apache.ibatis.jdbc.ScriptRunner;
 import org.apache.ibatis.session.SqlSession;
@@ -14,86 +9,101 @@
 import org.junit.BeforeClass;
 import org.junit.Test;
 
+import java.io.PrintWriter;
+import java.io.Reader;
+import java.sql.Connection;
+import java.sql.DriverManager;
+
 public class CglibNPELazyTest {
-    
-    private static SqlSessionFactory sqlSessionFactory;
-    
-    @BeforeClass
-    public static void initDatabase() throws Exception {
-        Connection conn = null;
-
-        try {
-            Class.forName("org.hsqldb.jdbcDriver");
-            conn = DriverManager.getConnection("jdbc:hsqldb:mem:cglib_lazy_error", "sa",
-                    "");
-
-            Reader reader = Resources.getResourceAsReader("org/apache/ibatis/submitted/cglib_lazy_error/CreateDB.sql");
-
-            ScriptRunner runner = new ScriptRunner(conn);
-            runner.setLogWriter(null);
-            runner.setErrorLogWriter(new PrintWriter(System.err));
-            runner.runScript(reader);
-            conn.commit();
-            reader.close();
-
-            reader = Resources.getResourceAsReader("org/apache/ibatis/submitted/cglib_lazy_error/ibatisConfigLazy.xml");
-            sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
-            reader.close();
-        } finally {
-            if (conn != null) {
-                conn.close();
-            }
-        }
-    }
-    
-    @Test
-    public void testNoParent() {
-        SqlSession sqlSession = sqlSessionFactory.openSession();
-        PersonMapper personMapper = sqlSession.getMapper(PersonMapper.class);
-        Person person = personMapper.selectById(1);
-        Assert.assertNotNull("Persons must not be null", person);
-        Person parent = person.getParent();
-        Assert.assertNull("Parent must be null", parent);
-    }
-    @Test
-    public void testAncestorSelf() {
-        SqlSession sqlSession = sqlSessionFactory.openSession();
-        PersonMapper personMapper = sqlSession.getMapper(PersonMapper.class);
-        Person person = personMapper.selectById(1);
-        Assert.assertNotNull("Persons must not be null", person);
-        Person ancestor = person.getAncestor();
-        Assert.assertEquals("Ancestor must be John Smith sr.", person, ancestor);
-    }
-    @Test
-    public void testGrandParent() {
-        SqlSession sqlSession = sqlSessionFactory.openSession();
-        PersonMapper personMapper = sqlSession.getMapper(PersonMapper.class);
-        Person expectedParent = personMapper.selectById(2);
-        Person expectedGrandParent = personMapper.selectById(1);
-        Person person = personMapper.selectById(3);
-        Assert.assertNotNull("Persons must not be null", person);
-        Assert.assertEquals("Parent must be John Smith", expectedParent, person.getParent());
-        Assert.assertEquals("Parent must be John Smith sr.", expectedGrandParent, person.getParent().getParent());
-    }
-    @Test
-    public void testAncestor() {
-        SqlSession sqlSession = sqlSessionFactory.openSession();
-        PersonMapper personMapper = sqlSession.getMapper(PersonMapper.class);
-        Person expectedAncestor = personMapper.selectById(1);
-        Person person = personMapper.selectById(3);
-        Assert.assertNotNull("Persons must not be null", person);
-        Assert.assertEquals("Ancestor must be John Smith sr.", expectedAncestor, person.getAncestor());
-    }
-    @Test
-    public void testAncestorAfterQueryingParents() {
-        SqlSession sqlSession = sqlSessionFactory.openSession();
-        PersonMapper personMapper = sqlSession.getMapper(PersonMapper.class);
-        Person expectedAncestor = personMapper.selectById(1);
-        Person person = personMapper.selectById(3);
-        // Load ancestor indirectly.
-        Assert.assertNotNull("Persons must not be null", person);
-        Assert.assertNotNull("Parent must not be null", person.getParent());
-        Assert.assertNotNull("Grandparent must not be null", person.getParent().getParent());
-        Assert.assertEquals("Ancestor must be John Smith sr.", expectedAncestor, person.getAncestor());
-    }
+
+  private static SqlSessionFactory sqlSessionFactory;
+
+  @BeforeClass
+  public static void initDatabase() throws Exception {
+    Connection conn = null;
+
+    try {
+      Class.forName("org.hsqldb.jdbcDriver");
+      conn = DriverManager.getConnection("jdbc:hsqldb:mem:cglib_lazy_error", "sa",
+          "");
+
+      Reader reader = Resources.getResourceAsReader("org/apache/ibatis/submitted/cglib_lazy_error/CreateDB.sql");
+
+      ScriptRunner runner = new ScriptRunner(conn);
+      runner.setLogWriter(null);
+      runner.setErrorLogWriter(new PrintWriter(System.err));
+      runner.runScript(reader);
+      conn.commit();
+      reader.close();
+
+      reader = Resources.getResourceAsReader("org/apache/ibatis/submitted/cglib_lazy_error/ibatisConfigLazy.xml");
+      sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
+      sqlSessionFactory.getConfiguration().setLazyLoadingEnabled(true);
+      sqlSessionFactory.getConfiguration().setAggressiveLazyLoading(false);
+      reader.close();
+    } finally {
+      if (conn != null) {
+        conn.close();
+      }
+    }
+  }
+
+  @Test
+  public void testNoParent() {
+    SqlSession sqlSession = sqlSessionFactory.openSession();
+    PersonMapper personMapper = sqlSession.getMapper(PersonMapper.class);
+    Person person = personMapper.selectById(1);
+    Assert.assertNotNull("Persons must not be null", person);
+    Person parent = person.getParent();
+    Assert.assertNull("Parent must be null", parent);
+  }
+
+  @Test
+  public void testAncestorSelf() {
+    SqlSession sqlSession = sqlSessionFactory.openSession();
+    PersonMapper personMapper = sqlSession.getMapper(PersonMapper.class);
+    Person person = personMapper.selectById(1);
+    Assert.assertNotNull("Persons must not be null", person);
+    Person ancestor = person.getAncestor();
+    Assert.assertEquals("Ancestor must be John Smith sr.", person, ancestor);
+  }
+
+  @Test
+  public void testAncestorAfterQueryingParents() {
+    SqlSession sqlSession = sqlSessionFactory.openSession();
+    PersonMapper personMapper = sqlSession.getMapper(PersonMapper.class);
+    Person expectedAncestor = personMapper.selectById(1);
+    Person person = personMapper.selectById(3);
+    // Load ancestor indirectly.
+    Assert.assertNotNull("Persons must not be null", person);
+    Assert.assertNotNull("Parent must not be null", person.getParent());
+    Assert.assertNotNull("Grandparent must not be null", person.getParent().getParent());
+    Assert.assertEquals("Ancestor must be John Smith sr.", expectedAncestor, person.getAncestor());
+  }
+
+  @Test
+  public void testGrandParent() {
+    SqlSession sqlSession = sqlSessionFactory.openSession();
+    PersonMapper personMapper = sqlSession.getMapper(PersonMapper.class);
+    Person expectedParent = personMapper.selectById(2);
+    Person expectedGrandParent = personMapper.selectById(1);
+    Person person = personMapper.selectById(3);
+    Assert.assertNotNull("Persons must not be null", person);
+    final Person actualParent = person.getParent();
+    final Person actualGrandParent = person.getParent().getParent();
+    Assert.assertEquals(expectedParent, actualParent);
+    Assert.assertEquals(expectedGrandParent, actualGrandParent);
+  }
+
+  @Test
+  public void testAncestor() {
+    SqlSession sqlSession = sqlSessionFactory.openSession();
+    PersonMapper personMapper = sqlSession.getMapper(PersonMapper.class);
+    Person expectedAncestor = personMapper.selectById(1);
+    Person person = personMapper.selectById(3);
+    Assert.assertNotNull("Persons must not be null", person);
+    final Person actualAncestor = person.getAncestor();
+    Assert.assertEquals(expectedAncestor, actualAncestor);
+  }
+
 }

Modified: ibatis/java/ibatis-3/trunk/ibatis-3-core/src/test/java/org/apache/ibatis/submitted/cglib_lazy_error/CglibNPETest.java
URL: http://svn.apache.org/viewvc/ibatis/java/ibatis-3/trunk/ibatis-3-core/src/test/java/org/apache/ibatis/submitted/cglib_lazy_error/CglibNPETest.java?rev=909700&r1=909699&r2=909700&view=diff
==============================================================================
--- ibatis/java/ibatis-3/trunk/ibatis-3-core/src/test/java/org/apache/ibatis/submitted/cglib_lazy_error/CglibNPETest.java (original)
+++ ibatis/java/ibatis-3/trunk/ibatis-3-core/src/test/java/org/apache/ibatis/submitted/cglib_lazy_error/CglibNPETest.java Sat Feb 13 03:01:44 2010
@@ -1,10 +1,5 @@
 package org.apache.ibatis.submitted.cglib_lazy_error;
 
-import java.io.PrintWriter;
-import java.io.Reader;
-import java.sql.Connection;
-import java.sql.DriverManager;
-
 import org.apache.ibatis.io.Resources;
 import org.apache.ibatis.jdbc.ScriptRunner;
 import org.apache.ibatis.session.SqlSession;
@@ -14,88 +9,97 @@
 import org.junit.BeforeClass;
 import org.junit.Test;
 
+import java.io.PrintWriter;
+import java.io.Reader;
+import java.sql.Connection;
+import java.sql.DriverManager;
+
 public class CglibNPETest {
-    
-    private static SqlSessionFactory sqlSessionFactory;
-    
-    @BeforeClass
-    public static void initDatabase() throws Exception {
-        Connection conn = null;
-
-        try {
-            Class.forName("org.hsqldb.jdbcDriver");
-            conn = DriverManager.getConnection("jdbc:hsqldb:mem:cglib_lazy_eager_no_error", "sa",
-                    "");
-
-            Reader reader = Resources.getResourceAsReader("org/apache/ibatis/submitted/cglib_lazy_error/CreateDB.sql");
-
-            ScriptRunner runner = new ScriptRunner(conn);
-            runner.setLogWriter(null);
-            runner.setErrorLogWriter(new PrintWriter(System.err));
-            runner.runScript(reader);
-            conn.commit();
-            reader.close();
-
-            reader = Resources.getResourceAsReader("org/apache/ibatis/submitted/cglib_lazy_error/ibatisConfig.xml");
-            sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
-            reader.close();
-        } finally {
-            if (conn != null) {
-                conn.close();
-            }
-        }
-    }
-    
-    @Test
-    public void testNoParent() {
-        SqlSession sqlSession = sqlSessionFactory.openSession();
-        PersonMapper personMapper = sqlSession.getMapper(PersonMapper.class);
-        Person person = personMapper.selectById(1);
-        Assert.assertNotNull("Persons must not be null", person);
-        Person parent = person.getParent();
-        Assert.assertNull("Parent must be null", parent);
-    }
-    @Test
-    public void testAncestorSelf() {
-        SqlSession sqlSession = sqlSessionFactory.openSession();
-        PersonMapper personMapper = sqlSession.getMapper(PersonMapper.class);
-        Person person = personMapper.selectById(1);
-        Assert.assertNotNull("Persons must not be null", person);
-        Person ancestor = person.getAncestor();
-        Assert.assertEquals("Ancestor must be John Smith sr.", person, ancestor);
-    }
-    @Test
-    public void testGrandParent() {
-        SqlSession sqlSession = sqlSessionFactory.openSession();
-        PersonMapper personMapper = sqlSession.getMapper(PersonMapper.class);
-        Person expectedParent = personMapper.selectById(2);
-        Person expectedGrandParent = personMapper.selectById(1);
-        Person person = personMapper.selectById(3);
-        Assert.assertNotNull("Persons must not be null", person);
-        Assert.assertEquals("Parent must be John Smith", expectedParent, person.getParent());
-        Assert.assertEquals("Parent must be John Smith sr.", expectedGrandParent, person.getParent().getParent());
-    }
-    @Test
-    public void testAncestor() {
-        SqlSession sqlSession = sqlSessionFactory.openSession();
-        PersonMapper personMapper = sqlSession.getMapper(PersonMapper.class);
-        Person expectedAncestor = personMapper.selectById(1);
-        Person person = personMapper.selectById(3);
-        Assert.assertNotNull("Persons must not be null", person);
-        Assert.assertEquals("Ancestor must be John Smith sr.", expectedAncestor, person.getAncestor());
-    }
-    @Test
-    public void testAncestorAfterQueryingParents() {
-        SqlSession sqlSession = sqlSessionFactory.openSession();
-        PersonMapper personMapper = sqlSession.getMapper(PersonMapper.class);
-        Person expectedAncestor = personMapper.selectById(1);
-        Person person = personMapper.selectById(3);
-        // Load ancestor indirectly.
-        Assert.assertNotNull("Persons must not be null", person);
-        Assert.assertNotNull("Parent must not be null", person.getParent());
-        Assert.assertNotNull("Grandparent must not be null", person.getParent().getParent());
-        Assert.assertEquals("Ancestor must be John Smith sr.", expectedAncestor, person.getAncestor());
+
+  private static SqlSessionFactory sqlSessionFactory;
+
+  @BeforeClass
+  public static void initDatabase() throws Exception {
+    Connection conn = null;
+
+    try {
+      Class.forName("org.hsqldb.jdbcDriver");
+      conn = DriverManager.getConnection("jdbc:hsqldb:mem:cglib_lazy_eager_no_error", "sa",
+          "");
+
+      Reader reader = Resources.getResourceAsReader("org/apache/ibatis/submitted/cglib_lazy_error/CreateDB.sql");
+
+      ScriptRunner runner = new ScriptRunner(conn);
+      runner.setLogWriter(null);
+      runner.setErrorLogWriter(new PrintWriter(System.err));
+      runner.runScript(reader);
+      conn.commit();
+      reader.close();
+
+      reader = Resources.getResourceAsReader("org/apache/ibatis/submitted/cglib_lazy_error/ibatisConfig.xml");
+      sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
+      reader.close();
+    } finally {
+      if (conn != null) {
+        conn.close();
+      }
     }
+  }
+
+  @Test
+  public void testNoParent() {
+    SqlSession sqlSession = sqlSessionFactory.openSession();
+    PersonMapper personMapper = sqlSession.getMapper(PersonMapper.class);
+    Person person = personMapper.selectById(1);
+    Assert.assertNotNull("Persons must not be null", person);
+    Person parent = person.getParent();
+    Assert.assertNull("Parent must be null", parent);
+  }
+
+  @Test
+  public void testAncestorSelf() {
+    SqlSession sqlSession = sqlSessionFactory.openSession();
+    PersonMapper personMapper = sqlSession.getMapper(PersonMapper.class);
+    Person person = personMapper.selectById(1);
+    Assert.assertNotNull("Persons must not be null", person);
+    Person ancestor = person.getAncestor();
+    Assert.assertEquals("Ancestor must be John Smith sr.", person, ancestor);
+  }
+
+  @Test
+  public void testGrandParent() {
+    SqlSession sqlSession = sqlSessionFactory.openSession();
+    PersonMapper personMapper = sqlSession.getMapper(PersonMapper.class);
+    Person expectedParent = personMapper.selectById(2);
+    Person expectedGrandParent = personMapper.selectById(1);
+    Person person = personMapper.selectById(3);
+    Assert.assertNotNull("Persons must not be null", person);
+    Assert.assertEquals("Parent must be John Smith", expectedParent, person.getParent());
+    Assert.assertEquals("Parent must be John Smith sr.", expectedGrandParent, person.getParent().getParent());
+  }
+
+  @Test
+  public void testAncestor() {
+    SqlSession sqlSession = sqlSessionFactory.openSession();
+    PersonMapper personMapper = sqlSession.getMapper(PersonMapper.class);
+    Person expectedAncestor = personMapper.selectById(1);
+    Person person = personMapper.selectById(3);
+    Assert.assertNotNull("Persons must not be null", person);
+    Assert.assertEquals("Ancestor must be John Smith sr.", expectedAncestor, person.getAncestor());
+  }
+
+  @Test
+  public void testAncestorAfterQueryingParents() {
+    SqlSession sqlSession = sqlSessionFactory.openSession();
+    PersonMapper personMapper = sqlSession.getMapper(PersonMapper.class);
+    Person expectedAncestor = personMapper.selectById(1);
+    Person person = personMapper.selectById(3);
+    // Load ancestor indirectly.
+    Assert.assertNotNull("Persons must not be null", person);
+    Assert.assertNotNull("Parent must not be null", person.getParent());
+    Assert.assertNotNull("Grandparent must not be null", person.getParent().getParent());
+    Assert.assertEquals("Ancestor must be John Smith sr.", expectedAncestor, person.getAncestor());
+  }
 
   @Test
   public void testInsertBetweenTwoSelects() {
@@ -107,15 +111,15 @@
       Person selected3 = personMapper.selectById(3);
       selected1.setId(4L);
       int rows = personMapper.insertPerson(selected1);
-      Assert.assertEquals(1,rows);
+      Assert.assertEquals(1, rows);
       selected1 = personMapper.selectById(1);
       selected2 = personMapper.selectById(2);
       selected3 = personMapper.selectById(3);
       Person selected4 = personMapper.selectById(4);
-      Assert.assertEquals(1,selected1.getId().longValue());
-      Assert.assertEquals(2,selected2.getId().longValue());
-      Assert.assertEquals(3,selected3.getId().longValue());
-      Assert.assertEquals(4,selected4.getId().longValue());
+      Assert.assertEquals(1, selected1.getId().longValue());
+      Assert.assertEquals(2, selected2.getId().longValue());
+      Assert.assertEquals(3, selected3.getId().longValue());
+      Assert.assertEquals(4, selected4.getId().longValue());
 
     } finally {
       sqlSession.close();
@@ -128,7 +132,7 @@
     try {
       PersonMapper personMapper = sqlSession.getMapper(PersonMapper.class);
       Person selected1 = personMapper.selectByStringId("1");
-      Assert.assertEquals(1,selected1.getId().longValue());
+      Assert.assertEquals(1, selected1.getId().longValue());
 
     } finally {
       sqlSession.close();

Modified: ibatis/java/ibatis-3/trunk/ibatis-3-core/src/test/java/org/apache/ibatis/submitted/cglib_lazy_error/CreateDB.sql
URL: http://svn.apache.org/viewvc/ibatis/java/ibatis-3/trunk/ibatis-3-core/src/test/java/org/apache/ibatis/submitted/cglib_lazy_error/CreateDB.sql?rev=909700&r1=909699&r2=909700&view=diff
==============================================================================
--- ibatis/java/ibatis-3/trunk/ibatis-3-core/src/test/java/org/apache/ibatis/submitted/cglib_lazy_error/CreateDB.sql (original)
+++ ibatis/java/ibatis-3/trunk/ibatis-3-core/src/test/java/org/apache/ibatis/submitted/cglib_lazy_error/CreateDB.sql Sat Feb 13 03:01:44 2010
@@ -1,8 +1,8 @@
 create table person (
-  id int,
-  firstName varchar(100),
-  lastName varchar(100),
-  parent int DEFAULT NULL
+id int,
+firstName varchar(100),
+lastName varchar(100),
+parent int DEFAULT NULL
 );
 
 INSERT INTO person (id, firstName, lastName, parent)

Modified: ibatis/java/ibatis-3/trunk/ibatis-3-core/src/test/java/org/apache/ibatis/submitted/cglib_lazy_error/Person.java
URL: http://svn.apache.org/viewvc/ibatis/java/ibatis-3/trunk/ibatis-3-core/src/test/java/org/apache/ibatis/submitted/cglib_lazy_error/Person.java?rev=909700&r1=909699&r2=909700&view=diff
==============================================================================
--- ibatis/java/ibatis-3/trunk/ibatis-3-core/src/test/java/org/apache/ibatis/submitted/cglib_lazy_error/Person.java (original)
+++ ibatis/java/ibatis-3/trunk/ibatis-3-core/src/test/java/org/apache/ibatis/submitted/cglib_lazy_error/Person.java Sat Feb 13 03:01:44 2010
@@ -1,58 +1,72 @@
 package org.apache.ibatis.submitted.cglib_lazy_error;
 
 public class Person {
-    
-    private Long id;
-    private String firstName;
-    private String lastName;
-    private Person parent;
-    public Person getAncestor() {
-        if (getParent() == null) {
-            return this;
-        } else {
-            return getParent().getAncestor();
-        }
-    }
-    
-    
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (obj instanceof Person) {
-            return this.getId() == ((Person) obj).getId();
-        }
-        return false;
-    }
-    @Override
-    public int hashCode() {
-        return id != null ? id.intValue() : null;
+
+  private Long id;
+  private String firstName;
+  private String lastName;
+  private Person parent;
+
+  public Person getAncestor() {
+    if (getParent() == null) {
+      return this;
+    } else {
+      return getParent().getAncestor();
     }
+  }
+
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) return true;
+    if (!(o instanceof Person)) return false;
+
+    Person person = (Person) o;
     
-    
-    public String getFirstName() {
-        return firstName;
-    }
-    public void setFirstName(String firstName) {
-        this.firstName = firstName;
-    }
-    public String getLastName() {
-        return lastName;
-    }
-    public void setLastName(String lastName) {
-        this.lastName = lastName;
-    }
-    public Long getId() {
-        return id;
-    }
-    public void setId(Long id) {
-        this.id = id;
-    }
-    public Person getParent() {
-        return parent;
-    }
-    public void setParent(Person parent) {
-        this.parent = parent;
-    }
+    if (id != null ? !id.equals(person.id) : person.id != null) return false;
+
+    return true;
+  }
+
+  @Override
+  public int hashCode() {
+    return id != null ? id.hashCode() : 0;
+  }
+
+  @Override
+  public String toString() {
+    return id + ": " + firstName + " " + lastName + " ("+parent+")";
+  }
+
+  public String getFirstName() {
+    return firstName;
+  }
+
+  public void setFirstName(String firstName) {
+    this.firstName = firstName;
+  }
+
+  public String getLastName() {
+    return lastName;
+  }
+
+  public void setLastName(String lastName) {
+    this.lastName = lastName;
+  }
+
+  public Long getId() {
+    return id;
+  }
+
+  public void setId(Long id) {
+    this.id = id;
+  }
+
+  public Person getParent() {
+    return parent;
+  }
+
+  public void setParent(Person parent) {
+    this.parent = parent;
+  }
 }

Modified: ibatis/java/ibatis-3/trunk/ibatis-3-core/src/test/java/org/apache/ibatis/submitted/cglib_lazy_error/Person.xml
URL: http://svn.apache.org/viewvc/ibatis/java/ibatis-3/trunk/ibatis-3-core/src/test/java/org/apache/ibatis/submitted/cglib_lazy_error/Person.xml?rev=909700&r1=909699&r2=909700&view=diff
==============================================================================
--- ibatis/java/ibatis-3/trunk/ibatis-3-core/src/test/java/org/apache/ibatis/submitted/cglib_lazy_error/Person.xml (original)
+++ ibatis/java/ibatis-3/trunk/ibatis-3-core/src/test/java/org/apache/ibatis/submitted/cglib_lazy_error/Person.xml Sat Feb 13 03:01:44 2010
@@ -4,38 +4,41 @@
     "http://ibatis.apache.org/dtd/ibatis-3-mapper.dtd">
 
 <mapper namespace="org.apache.ibatis.submitted.cglib_lazy_error.PersonMapper">
-    
-    <resultMap id="personMap" type="Person">
-        <id property="id" column="Person_id"/>
-        <result property="firstName" column="Person_firstName"/>
-        <result property="lastName" column="Person_lastName"/>
-        <association property="parent" column="Person_parent" select="org.apache.ibatis.submitted.cglib_lazy_error.PersonMapper.selectById"/>
-    </resultMap>
-    
-    
-    <sql id="columns">
-        Person.id AS Person_id,
-        Person.firstName AS Person_firstName,
-        Person.lastName AS Person_lastName,
-        Person.parent AS Person_parent
-    </sql>
-    
-    
-    <select id="selectById" resultMap="personMap" parameterType="int">
-        SELECT <include refid="columns"/>
-        FROM Person
-        WHERE id = #{id,jdbcType=INTEGER}
-    </select>
-
-    <select id="selectByStringId" resultMap="personMap" parameterType="String">
-        SELECT <include refid="columns"/>
-        FROM Person
-        WHERE id = ${value}
-    </select>
-
-    <insert id="insertPerson">
-      INSERT INTO person (id, firstName, lastName, parent)
-      VALUES (#{id}, #{firstName}, #{lastName}, null);
-    </insert>
-    
+
+  <resultMap id="personMap" type="Person">
+    <id property="id" column="Person_id"/>
+    <result property="firstName" column="Person_firstName"/>
+    <result property="lastName" column="Person_lastName"/>
+    <association property="parent" column="Person_parent"
+                 select="selectById"/>
+  </resultMap>
+
+
+  <sql id="columns">
+    Person.id AS Person_id,
+    Person.firstName AS Person_firstName,
+    Person.lastName AS Person_lastName,
+    Person.parent AS Person_parent
+  </sql>
+
+
+  <select id="selectById" resultMap="personMap" parameterType="int">
+    SELECT
+    <include refid="columns"/>
+    FROM Person
+    WHERE id = #{id,jdbcType=INTEGER}
+  </select>
+
+  <select id="selectByStringId" resultMap="personMap" parameterType="String">
+    SELECT
+    <include refid="columns"/>
+    FROM Person
+    WHERE id = ${value}
+  </select>
+
+  <insert id="insertPerson">
+    INSERT INTO person (id, firstName, lastName, parent)
+    VALUES (#{id}, #{firstName}, #{lastName}, null);
+  </insert>
+
 </mapper>

Modified: ibatis/java/ibatis-3/trunk/ibatis-3-core/src/test/java/org/apache/ibatis/submitted/cglib_lazy_error/PersonMapper.java
URL: http://svn.apache.org/viewvc/ibatis/java/ibatis-3/trunk/ibatis-3-core/src/test/java/org/apache/ibatis/submitted/cglib_lazy_error/PersonMapper.java?rev=909700&r1=909699&r2=909700&view=diff
==============================================================================
--- ibatis/java/ibatis-3/trunk/ibatis-3-core/src/test/java/org/apache/ibatis/submitted/cglib_lazy_error/PersonMapper.java (original)
+++ ibatis/java/ibatis-3/trunk/ibatis-3-core/src/test/java/org/apache/ibatis/submitted/cglib_lazy_error/PersonMapper.java Sat Feb 13 03:01:44 2010
@@ -1,9 +1,11 @@
 package org.apache.ibatis.submitted.cglib_lazy_error;
 
 public interface PersonMapper {
-    
-    public Person selectById(int id);
-    public Person selectByStringId(String id);
-    public int insertPerson (Person person);
+
+  public Person selectById(int id);
+
+  public Person selectByStringId(String id);
+
+  public int insertPerson(Person person);
 
 }

Modified: ibatis/java/ibatis-3/trunk/ibatis-3-core/src/test/java/org/apache/ibatis/submitted/cglib_lazy_error/ibatisConfig.xml
URL: http://svn.apache.org/viewvc/ibatis/java/ibatis-3/trunk/ibatis-3-core/src/test/java/org/apache/ibatis/submitted/cglib_lazy_error/ibatisConfig.xml?rev=909700&r1=909699&r2=909700&view=diff
==============================================================================
--- ibatis/java/ibatis-3/trunk/ibatis-3-core/src/test/java/org/apache/ibatis/submitted/cglib_lazy_error/ibatisConfig.xml (original)
+++ ibatis/java/ibatis-3/trunk/ibatis-3-core/src/test/java/org/apache/ibatis/submitted/cglib_lazy_error/ibatisConfig.xml Sat Feb 13 03:01:44 2010
@@ -4,22 +4,22 @@
     "http://ibatis.apache.org/dtd/ibatis-3-config.dtd">
 
 <configuration>
-    <typeAliases>
-        <typeAlias alias="Person" type="org.apache.ibatis.submitted.cglib_lazy_error.Person"/>
-    </typeAliases>
-    
-    <environments default="test">
-        <environment id="test">
-            <transactionManager type="JDBC"></transactionManager>
-            <dataSource type="UNPOOLED">
-                <property name="driver" value="org.hsqldb.jdbcDriver"/>
-                <property name="url" value="jdbc:hsqldb:mem:cglib_lazy_eager_no_error"/>
-                <property name="username" value="sa"/>
-            </dataSource>
-        </environment>
-    </environments>
-    
-    <mappers>
-        <mapper resource="org/apache/ibatis/submitted/cglib_lazy_error/Person.xml"/>
-    </mappers>
+  <typeAliases>
+    <typeAlias alias="Person" type="org.apache.ibatis.submitted.cglib_lazy_error.Person"/>
+  </typeAliases>
+
+  <environments default="test">
+    <environment id="test">
+      <transactionManager type="JDBC"></transactionManager>
+      <dataSource type="UNPOOLED">
+        <property name="driver" value="org.hsqldb.jdbcDriver"/>
+        <property name="url" value="jdbc:hsqldb:mem:cglib_lazy_eager_no_error"/>
+        <property name="username" value="sa"/>
+      </dataSource>
+    </environment>
+  </environments>
+
+  <mappers>
+    <mapper resource="org/apache/ibatis/submitted/cglib_lazy_error/Person.xml"/>
+  </mappers>
 </configuration>

Modified: ibatis/java/ibatis-3/trunk/ibatis-3-core/src/test/java/org/apache/ibatis/submitted/cglib_lazy_error/ibatisConfigLazy.xml
URL: http://svn.apache.org/viewvc/ibatis/java/ibatis-3/trunk/ibatis-3-core/src/test/java/org/apache/ibatis/submitted/cglib_lazy_error/ibatisConfigLazy.xml?rev=909700&r1=909699&r2=909700&view=diff
==============================================================================
--- ibatis/java/ibatis-3/trunk/ibatis-3-core/src/test/java/org/apache/ibatis/submitted/cglib_lazy_error/ibatisConfigLazy.xml (original)
+++ ibatis/java/ibatis-3/trunk/ibatis-3-core/src/test/java/org/apache/ibatis/submitted/cglib_lazy_error/ibatisConfigLazy.xml Sat Feb 13 03:01:44 2010
@@ -4,26 +4,26 @@
     "http://ibatis.apache.org/dtd/ibatis-3-config.dtd">
 
 <configuration>
-    <settings>
-        <setting name="lazyLoadingEnabled" value="true"/>
-    </settings>
-    
-    <typeAliases>
-        <typeAlias alias="Person" type="org.apache.ibatis.submitted.cglib_lazy_error.Person"/>
-    </typeAliases>
-    
-    <environments default="test">
-        <environment id="test">
-            <transactionManager type="JDBC"></transactionManager>
-            <dataSource type="UNPOOLED">
-                <property name="driver" value="org.hsqldb.jdbcDriver"/>
-                <property name="url" value="jdbc:hsqldb:mem:cglib_lazy_error"/>
-                <property name="username" value="sa"/>
-            </dataSource>
-        </environment>
-    </environments>
-    
-    <mappers>
-        <mapper resource="org/apache/ibatis/submitted/cglib_lazy_error/Person.xml"/>
-    </mappers>
+  <settings>
+    <setting name="lazyLoadingEnabled" value="true"/>
+  </settings>
+
+  <typeAliases>
+    <typeAlias alias="Person" type="org.apache.ibatis.submitted.cglib_lazy_error.Person"/>
+  </typeAliases>
+
+  <environments default="test">
+    <environment id="test">
+      <transactionManager type="JDBC"></transactionManager>
+      <dataSource type="UNPOOLED">
+        <property name="driver" value="org.hsqldb.jdbcDriver"/>
+        <property name="url" value="jdbc:hsqldb:mem:cglib_lazy_error"/>
+        <property name="username" value="sa"/>
+      </dataSource>
+    </environment>
+  </environments>
+
+  <mappers>
+    <mapper resource="org/apache/ibatis/submitted/cglib_lazy_error/Person.xml"/>
+  </mappers>
 </configuration>

Modified: ibatis/java/ibatis-3/trunk/version.properties
URL: http://svn.apache.org/viewvc/ibatis/java/ibatis-3/trunk/version.properties?rev=909700&r1=909699&r2=909700&view=diff
==============================================================================
--- ibatis/java/ibatis-3/trunk/version.properties (original)
+++ ibatis/java/ibatis-3/trunk/version.properties Sat Feb 13 03:01:44 2010
@@ -1,5 +1,5 @@
 #Build version info
-#Sat Jan 23 19:23:01 MST 2010
+#Fri Feb 12 19:52:58 MST 2010
 version=3.0.0
-buildDate=2010/01/23 19\:23
-buildNum=228
+buildDate=2010/02/12 19\:52
+buildNum=230