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 2009/03/01 20:06:56 UTC

svn commit: r749075 - in /ibatis/trunk/java/ibatis-3/ibatis-3-core/src: main/java/org/apache/ibatis/annotations/ main/java/org/apache/ibatis/binding/ main/java/org/apache/ibatis/parser/ test/java/databases/blog/ test/java/domain/blog/ test/java/org/apa...

Author: cbegin
Date: Sun Mar  1 19:06:55 2009
New Revision: 749075

URL: http://svn.apache.org/viewvc?rev=749075&view=rev
Log:
added recursive join mapping.  
Uncovered a new bug: If nested result map has empty rowset (i.e. no results) then the parent of the resultMap will not be loaded.  E.g. is A has many B, and if B is empty, then A won't be loaded.

Modified:
    ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/annotations/Annotations.java
    ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/binding/MapperAnnotationParser.java
    ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/parser/MapperParser.java
    ibatis/trunk/java/ibatis-3/ibatis-3-core/src/test/java/databases/blog/blog-derby-dataload.sql
    ibatis/trunk/java/ibatis-3/ibatis-3-core/src/test/java/domain/blog/Comment.java
    ibatis/trunk/java/ibatis-3/ibatis-3-core/src/test/java/domain/blog/Post.java
    ibatis/trunk/java/ibatis-3/ibatis-3-core/src/test/java/domain/blog/Tag.java
    ibatis/trunk/java/ibatis-3/ibatis-3-core/src/test/java/org/apache/ibatis/binding/BindingTest.java
    ibatis/trunk/java/ibatis-3/ibatis-3-core/src/test/java/org/apache/ibatis/binding/BoundAuthorMapper.java
    ibatis/trunk/java/ibatis-3/ibatis-3-core/src/test/java/org/apache/ibatis/binding/BoundBlogMapper.java
    ibatis/trunk/java/ibatis-3/ibatis-3-core/src/test/java/org/apache/ibatis/binding/IbatisConfig.java

Modified: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/annotations/Annotations.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/annotations/Annotations.java?rev=749075&r1=749074&r2=749075&view=diff
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/annotations/Annotations.java (original)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/annotations/Annotations.java Sun Mar  1 19:06:55 2009
@@ -41,10 +41,25 @@
     Class javaType() default void.class;
     JdbcType jdbcType() default JdbcType.UNDEFINED;
     Class typeHandler() default void.class;
-    String collectionSelect() default "";
-    Results collectionResults() default @Results;
-    String associationSelect() default "";
-    Results associationResults() default @Results;
+    One one() default @One;
+    Many many() default @Many(javaType = void.class);
+  }
+
+  @Retention(RetentionPolicy.RUNTIME)
+  @Target(ElementType.METHOD)
+  public static @interface One {
+    String select() default "";
+    ConstructorArgs constructor() default @ConstructorArgs;
+    Results results() default @Results;
+  }
+
+  @Retention(RetentionPolicy.RUNTIME)
+  @Target(ElementType.METHOD)
+  public static @interface Many {
+    Class javaType();
+    String select() default "";
+    ConstructorArgs constructor() default @ConstructorArgs;
+    Results results() default @Results;
   }
 
   @Retention(RetentionPolicy.RUNTIME)

Modified: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/binding/MapperAnnotationParser.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/binding/MapperAnnotationParser.java?rev=749075&r1=749074&r2=749075&view=diff
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/binding/MapperAnnotationParser.java (original)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/binding/MapperAnnotationParser.java Sun Mar  1 19:06:55 2009
@@ -1,13 +1,13 @@
 package org.apache.ibatis.binding;
 
 import static org.apache.ibatis.annotations.Annotations.*;
-import org.apache.ibatis.annotations.Annotations;
 import org.apache.ibatis.mapping.Configuration;
 import org.apache.ibatis.mapping.ResultFlag;
 import org.apache.ibatis.mapping.ResultSetType;
 import org.apache.ibatis.mapping.StatementType;
 import org.apache.ibatis.parser.MapperConfigurator;
 import org.apache.ibatis.type.JdbcType;
+import org.apache.ibatis.reflection.MetaClass;
 
 import java.lang.annotation.Annotation;
 import java.lang.reflect.*;
@@ -53,19 +53,39 @@
   private void parseResultsAndConstructorArgs(Method method) {
     ConstructorArgs args = method.getAnnotation(ConstructorArgs.class);
     Results results = method.getAnnotation(Results.class);
+    Class returnType = getReturnType(method);
+    String resultMapId = type.getName() + "." + method.getName();
     if (hasResults(method)) {
-      String resultMapId = type.getName() + "." + method.getName();
-      configurator.resultMapStart(resultMapId, getReturnType(method), null);
-      applyConstructorArgs(args);
-      applyResults(results);
-      configurator.resultMapEnd();
+      applyResultMap(resultMapId, returnType, argsIf(args), resultsIf(results));
     }
   }
 
-  private boolean hasResults(Method method) {
-    ConstructorArgs args = method.getAnnotation(ConstructorArgs.class);
-    Results results = method.getAnnotation(Results.class);
-    return results != null || args != null;
+  private void applyResultMap(String resultMapId, Class returnType, Arg[] args, Result[] results) {
+    applyNestedResultMaps(resultMapId, returnType, results);
+    configurator.resultMapStart(resultMapId, returnType, null);
+    applyConstructorArgs(args);
+    applyResults(resultMapId, results);
+    configurator.resultMapEnd();
+  }
+
+  private void applyNestedResultMaps(String resultMapId, Class returnType, Result[] results) {
+    if (results != null) {
+      for (Result result : results) {
+        ensureHasOnlyCollectionOrResultNotBoth(result);
+        if (hasCollection(result)) {
+          Class propertyType = result.many().javaType();
+          Arg[] nestedArgs = result.many().constructor().value();
+          Result[] nestedResults = result.many().results().value();
+          applyResultMap(nestedResultMapId(resultMapId, result),propertyType, nestedArgs, nestedResults);
+        }
+        if (hasAssociation(result)) {
+          Class propertyType = MetaClass.forClass(returnType).getSetterType(result.property());
+          Arg[] nestedArgs = result.one().constructor().value();
+          Result[] nestedResults = result.one().results().value();
+          applyResultMap(nestedResultMapId(resultMapId, result),propertyType, nestedArgs, nestedResults);
+        }
+      }
+    }
   }
 
   private void parseStatement(Method method) {
@@ -163,9 +183,9 @@
     return null;
   }
 
-  private void applyResults(Results results) {
-    if (results != null) {
-      for (Result result : results.value()) {
+  private void applyResults(String resultMapId, Result[] results) {
+    if (results.length > 0) {
+      for (Result result : results) {
         ArrayList<ResultFlag> flags = new ArrayList<ResultFlag>();
         if (result.id()) flags.add(ResultFlag.ID);
         configurator.resultMapping(
@@ -174,16 +194,16 @@
             result.javaType() == void.class ? null : result.javaType(),
             result.jdbcType() == JdbcType.UNDEFINED ? null : result.jdbcType(),
             null,
-            null,
+            hasCollectionOrAssociation(result) ? nestedResultMapId(resultMapId, result) : null,
             result.typeHandler() == void.class ? null : result.typeHandler(),
             flags);
       }
     }
   }
 
-  private void applyConstructorArgs(ConstructorArgs args) {
-    if (args != null) {
-      for (Arg arg : args.value()) {
+  private void applyConstructorArgs(Arg[] args) {
+    if (args.length > 0) {
+      for (Arg arg : args) {
         ArrayList<ResultFlag> flags = new ArrayList<ResultFlag>();
         flags.add(ResultFlag.CONSTRUCTOR);
         if (arg.id()) flags.add(ResultFlag.ID);
@@ -200,4 +220,42 @@
     }
   }
 
+  private String nestedResultMapId(String resultMapId, Result result) {
+    return resultMapId + "." + result.property();
+  }
+
+  private void ensureHasOnlyCollectionOrResultNotBoth(Result result) {
+    if (hasCollection(result) && hasAssociation(result)) {
+      throw new BindingException("On each result you can only use an association or a collection, not both!");
+    }
+  }
+
+  private boolean hasCollectionOrAssociation(Result result) {
+    return hasCollection(result) || hasAssociation(result);
+  }
+
+  private boolean hasAssociation(Result result) {
+    return result.one().constructor().value().length > 1
+        || result.one().results().value().length > 1;
+  }
+
+  private boolean hasCollection(Result result) {
+    return result.many().constructor().value().length > 1
+        || result.many().results().value().length > 1;
+  }
+
+  private boolean hasResults(Method method) {
+    ConstructorArgs args = method.getAnnotation(ConstructorArgs.class);
+    Results results = method.getAnnotation(Results.class);
+    return results != null || args != null;
+  }
+
+  private Result[] resultsIf(Results results) {
+    return results == null ? new Result[0] : results.value();
+  }
+
+  private Arg[] argsIf(ConstructorArgs args) {
+    return args == null ? new Arg[0] : args.value();
+  }
+
 }

Modified: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/parser/MapperParser.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/parser/MapperParser.java?rev=749075&r1=749074&r2=749075&view=diff
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/parser/MapperParser.java (original)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/parser/MapperParser.java Sun Mar  1 19:06:55 2009
@@ -14,10 +14,10 @@
 
   protected Reader reader;
   protected NodeletParser parser;
-  protected MapperConfigurator mapperBuilder;
+  protected MapperConfigurator mapperConfigurator;
 
   public MapperParser(Reader reader, Configuration configuration, String resource) {
-    this.mapperBuilder = new MapperConfigurator(configuration,resource);
+    this.mapperConfigurator = new MapperConfigurator(configuration,resource);
     this.reader = reader;
     this.parser = new NodeletParser();
     this.parser.addNodeletHandler(this);
@@ -41,13 +41,13 @@
   //  <configuration namespace="com.domain.MapperClass" />
   @Nodelet("/mapper")
   public void configurationElement(NodeletContext context) throws Exception {
-    mapperBuilder.namespace(context.getStringAttribute("namespace"));
+    mapperConfigurator.namespace(context.getStringAttribute("namespace"));
   }
 
   //  <cache type="LRU" flushInterval="3600000" size="1000" readOnly="false" />
   @Nodelet("/mapper/cache-ref")
   public void cacheRefElement(NodeletContext context) throws Exception {
-    mapperBuilder.cacheRef(context.getStringAttribute("namespace"));
+    mapperConfigurator.cacheRef(context.getStringAttribute("namespace"));
   }
 
   //  <cache type="LRU" flushInterval="3600000" size="1000" readOnly="false" />
@@ -63,7 +63,7 @@
     Integer size = context.getIntAttribute("size");
     boolean readOnly = context.getBooleanAttribute("readOnly", false);
     Properties props = context.getChildrenAsProperties();
-    mapperBuilder.cache(typeClass,evictionClass,flushInterval,size,readOnly,props);
+    mapperConfigurator.cache(typeClass,evictionClass,flushInterval,size,readOnly,props);
   }
 
   //  <parameterMap id="" type="">
@@ -72,7 +72,7 @@
     String id = context.getStringAttribute("id");
     String type = context.getStringAttribute("type");
     Class parameterClass = resolveClass(type);
-    mapperBuilder.parameterMapStart(id,parameterClass);
+    mapperConfigurator.parameterMapStart(id,parameterClass);
   }
 
   //  <parameterMap id="" type="">
@@ -90,13 +90,13 @@
     Class javaTypeClass = resolveClass(javaType);
     JdbcType jdbcTypeEnum = resolveJdbcType(jdbcType);
     Class typeHandlerClass = resolveClass(typeHandler);
-    mapperBuilder.parameterMapping(property,javaTypeClass,jdbcTypeEnum,resultMap,modeEnum,typeHandlerClass,numericScale);
+    mapperConfigurator.parameterMapping(property,javaTypeClass,jdbcTypeEnum,resultMap,modeEnum,typeHandlerClass,numericScale);
   }
 
   //  </parameterMap>
   @Nodelet("/mapper/parameterMap/end()")
   public void parameterMapClosingElement(NodeletContext context) throws Exception {
-    mapperBuilder.parameterMapEnd();
+    mapperConfigurator.parameterMapEnd();
   }
 
   //  <resultMap id="" type="" extends="">
@@ -106,7 +106,7 @@
     String type = context.getStringAttribute("type");
     String extend = context.getStringAttribute("extends");
     Class typeClass = resolveClass(type);
-    mapperBuilder.resultMapStart(id,typeClass,extend);
+    mapperConfigurator.resultMapStart(id,typeClass,extend);
   }
 
   //  <constructor>
@@ -174,7 +174,7 @@
     Class javaTypeClass = resolveClass(javaType);
     Class typeHandlerClass =  resolveClass(typeHandler);
     JdbcType jdbcTypeEnum = resolveJdbcType(jdbcType);
-    mapperBuilder.resultMapDiscriminatorStart(property,column,javaTypeClass,jdbcTypeEnum,nestedSelect,nestedResultMap,typeHandlerClass);
+    mapperConfigurator.resultMapDiscriminatorStart(property,column,javaTypeClass,jdbcTypeEnum,nestedSelect,nestedResultMap,typeHandlerClass);
   }
 
   //  <discriminator column="" javaType="" jdbcType="">
@@ -183,19 +183,19 @@
   public void resultMapDiscriminatorCaseElement(NodeletContext context) throws Exception {
     String value = context.getStringAttribute("value");
     String resultMap = context.getStringAttribute("resultMap");
-    mapperBuilder.resultMapDiscriminatorCase(value,resultMap);
+    mapperConfigurator.resultMapDiscriminatorCase(value,resultMap);
   }
 
   //  </discriminator>
   @Nodelet("/mapper/resultMap/discriminator/end()")
   public void resultMapDiscriminatorClosingElement(NodeletContext context) throws Exception {
-    mapperBuilder.resultMapDiscriminatorEnd();
+    mapperConfigurator.resultMapDiscriminatorEnd();
   }
 
   //  </resultMap>
   @Nodelet("/mapper/resultMap/end()")
   public void resultMapClosingElement(NodeletContext context) throws Exception {
-    mapperBuilder.resultMapEnd();
+    mapperConfigurator.resultMapEnd();
   }
 
   //  <select ...>
@@ -250,7 +250,7 @@
     Class resultTypeClass = resolveClass(resultType);
     String resultSetType = context.getStringAttribute("resultSetType");
     ResultSetType resultSetTypeEnum = resolveResultSetType(resultSetType);
-    mapperBuilder.statement(id,sql,fetchSize,timeout,parameterMap, parameterTypeClass,
+    mapperConfigurator.statement(id,sql,fetchSize,timeout,parameterMap, parameterTypeClass,
         resultMap, resultTypeClass,resultSetTypeEnum,isSelect,flushCache,useCache,statementType);
   }
 
@@ -266,7 +266,7 @@
     Class javaTypeClass = resolveClass(javaType);
     Class typeHandlerClass =  resolveClass(typeHandler);
     JdbcType jdbcTypeEnum = resolveJdbcType(jdbcType);
-    mapperBuilder.resultMapping(property,column,javaTypeClass,jdbcTypeEnum,nestedSelect,nestedResultMap,typeHandlerClass,flags);
+    mapperConfigurator.resultMapping(property,column,javaTypeClass,jdbcTypeEnum,nestedSelect,nestedResultMap,typeHandlerClass,flags);
   }
 
 }

Modified: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/test/java/databases/blog/blog-derby-dataload.sql
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/test/java/databases/blog/blog-derby-dataload.sql?rev=749075&r1=749074&r2=749075&view=diff
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/test/java/databases/blog/blog-derby-dataload.sql (original)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/test/java/databases/blog/blog-derby-dataload.sql Sun Mar  1 19:06:55 2009
@@ -24,5 +24,6 @@
 
 INSERT INTO comment (id,post_id,name,comment) VALUES (1,1,'troll','I disagree and think...');
 INSERT INTO comment (id,post_id,name,comment) VALUES (2,1,'anonymous','I agree and think troll is an...');
+INSERT INTO comment (id,post_id,name,comment) VALUES (4,2,'another','I don not agree and still think troll is an...');
 INSERT INTO comment (id,post_id,name,comment) VALUES (3,3,'rider','I prefer motorcycles to monster trucks...');
 

Modified: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/test/java/domain/blog/Comment.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/test/java/domain/blog/Comment.java?rev=749075&r1=749074&r2=749075&view=diff
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/test/java/domain/blog/Comment.java (original)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/test/java/domain/blog/Comment.java Sun Mar  1 19:06:55 2009
@@ -38,4 +38,8 @@
   public void setComment(String comment) {
     this.comment = comment;
   }
+
+  public String toString() {
+    return "Comment: " + id + " : " + name + " : " + comment;
+  }
 }

Modified: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/test/java/domain/blog/Post.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/test/java/domain/blog/Post.java?rev=749075&r1=749074&r2=749075&view=diff
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/test/java/domain/blog/Post.java (original)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/test/java/domain/blog/Post.java Sun Mar  1 19:06:55 2009
@@ -1,7 +1,6 @@
 package domain.blog;
 
-import java.util.Date;
-import java.util.List;
+import java.util.*;
 
 public class Post {
 
@@ -86,4 +85,8 @@
   public void setTags(List<Tag> tags) {
     this.tags = tags;
   }
+
+  public String toString() {
+    return "Post: " + id + " : " + subject + " : " + body + " : " + section + " : " + createdOn + " (" + author + ") (" + blog + ")";
+  }
 }

Modified: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/test/java/domain/blog/Tag.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/test/java/domain/blog/Tag.java?rev=749075&r1=749074&r2=749075&view=diff
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/test/java/domain/blog/Tag.java (original)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/test/java/domain/blog/Tag.java Sun Mar  1 19:06:55 2009
@@ -20,4 +20,8 @@
   public void setName(String name) {
     this.name = name;
   }
+
+  public String toString() {
+    return "Tag: " + id + " : " + name;
+  }
 }

Modified: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/test/java/org/apache/ibatis/binding/BindingTest.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/test/java/org/apache/ibatis/binding/BindingTest.java?rev=749075&r1=749074&r2=749075&view=diff
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/test/java/org/apache/ibatis/binding/BindingTest.java (original)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/test/java/org/apache/ibatis/binding/BindingTest.java Sun Mar  1 19:06:55 2009
@@ -1,12 +1,9 @@
 package org.apache.ibatis.binding;
 
-import org.apache.ibatis.session.SqlSessionFactory;
-import org.apache.ibatis.session.SqlSession;
-import org.junit.BeforeClass;
-import org.junit.Test;
-import static org.junit.Assert.*;
-
 import domain.blog.*;
+import org.apache.ibatis.session.*;
+import static org.junit.Assert.assertEquals;
+import org.junit.*;
 
 import java.util.*;
 
@@ -24,7 +21,7 @@
     try {
       BoundBlogMapper mapper = session.getMapper(BoundBlogMapper.class);
       List<Blog> blogs = mapper.selectBlogs();
-      assertEquals(2,blogs.size());
+      assertEquals(2, blogs.size());
     } finally {
       session.close();
     }
@@ -36,7 +33,7 @@
     try {
       BoundBlogMapper mapper = session.getMapper(BoundBlogMapper.class);
       List<Map> blogs = mapper.selectBlogsAsMaps();
-      assertEquals(2,blogs.size());
+      assertEquals(2, blogs.size());
     } finally {
       session.close();
     }
@@ -48,8 +45,21 @@
     try {
       BoundBlogMapper mapper = session.getMapper(BoundBlogMapper.class);
       List<Blog> blogs = mapper.selectBlogWithAssociations(1);
-      for(Blog blog : blogs) {
+      for (Blog blog : blogs) {
         System.out.println(blog);
+        for (Post post : blog.getPosts()) {
+          System.out.println("    " + post);
+          if (post.getComments() != null) {
+            for (Comment comment : post.getComments()) {
+              System.out.println("        " + comment);
+            }
+          }
+          if (post.getTags() != null) {
+            for (Tag tag : post.getTags()) {
+              System.out.println("        " + tag);
+            }
+          }
+        }
       }
     } finally {
       session.close();
@@ -62,8 +72,8 @@
     try {
       BoundBlogMapper mapper = session.getMapper(BoundBlogMapper.class);
       Blog blog = mapper.selectBlog(1);
-      assertEquals(1,blog.getId());
-      assertEquals("Jim Business",blog.getTitle());
+      assertEquals(1, blog.getId());
+      assertEquals("Jim Business", blog.getTitle());
     } finally {
       session.close();
     }
@@ -74,9 +84,13 @@
     SqlSession session = sqlSessionFactory.openSession();
     try {
       BoundBlogMapper mapper = session.getMapper(BoundBlogMapper.class);
-      Map blog = mapper.selectBlogAsMap(new HashMap() {{put("id",1);}});
-      assertEquals(1,blog.get("ID"));
-      assertEquals("Jim Business",blog.get("TITLE"));
+      Map blog = mapper.selectBlogAsMap(new HashMap() {
+        {
+          put("id", 1);
+        }
+      });
+      assertEquals(1, blog.get("ID"));
+      assertEquals("Jim Business", blog.get("TITLE"));
     } finally {
       session.close();
     }
@@ -88,10 +102,10 @@
     try {
       BoundAuthorMapper mapper = session.getMapper(BoundAuthorMapper.class);
       Author author = mapper.selectAuthor(101);
-      assertEquals(101,author.getId());
-      assertEquals("jim",author.getUsername());
-      assertEquals("********",author.getPassword());
-      assertEquals("jim@ibatis.apache.org",author.getEmail());
+      assertEquals(101, author.getId());
+      assertEquals("jim", author.getUsername());
+      assertEquals("********", author.getPassword());
+      assertEquals("jim@ibatis.apache.org", author.getEmail());
       assertEquals("", author.getBio());
     } finally {
       session.close();
@@ -104,10 +118,10 @@
     try {
       BoundAuthorMapper mapper = session.getMapper(BoundAuthorMapper.class);
       Author author = mapper.selectAuthorConstructor(101);
-      assertEquals(101,author.getId());
-      assertEquals("jim",author.getUsername());
-      assertEquals("********",author.getPassword());
-      assertEquals("jim@ibatis.apache.org",author.getEmail());
+      assertEquals(101, author.getId());
+      assertEquals("jim", author.getUsername());
+      assertEquals("********", author.getPassword());
+      assertEquals("jim@ibatis.apache.org", author.getEmail());
       assertEquals("", author.getBio());
     } finally {
       session.close();

Modified: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/test/java/org/apache/ibatis/binding/BoundAuthorMapper.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/test/java/org/apache/ibatis/binding/BoundAuthorMapper.java?rev=749075&r1=749074&r2=749075&view=diff
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/test/java/org/apache/ibatis/binding/BoundAuthorMapper.java (original)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/test/java/org/apache/ibatis/binding/BoundAuthorMapper.java Sun Mar  1 19:06:55 2009
@@ -6,6 +6,8 @@
 
 public interface BoundAuthorMapper {
 
+  //======================================================
+
   @ConstructorArgs({
     @Arg(column = "AUTHOR_ID", javaType = Integer.class)
       })
@@ -25,6 +27,7 @@
       "FROM AUTHOR WHERE ID = #{id}"})
   Author selectAuthor(int id);
 
+  //======================================================
 
   @ConstructorArgs({
     @Arg(column = "AUTHOR_ID", javaType = Integer.class),
@@ -45,4 +48,6 @@
       "FROM AUTHOR WHERE ID = #{id}"})
   Author selectAuthorConstructor(int id);
 
+  //======================================================
+
 }

Modified: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/test/java/org/apache/ibatis/binding/BoundBlogMapper.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/test/java/org/apache/ibatis/binding/BoundBlogMapper.java?rev=749075&r1=749074&r2=749075&view=diff
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/test/java/org/apache/ibatis/binding/BoundBlogMapper.java (original)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/test/java/org/apache/ibatis/binding/BoundBlogMapper.java Sun Mar  1 19:06:55 2009
@@ -8,32 +8,70 @@
 @CacheDomain
 public interface BoundBlogMapper {
 
+  //======================================================
+
   @Select({
       "SELECT *",
       "FROM blog"
       })
   List<Blog> selectBlogs();
 
+  //======================================================
+
   @Select({
       "SELECT *",
       "FROM blog"
       })
   List<Map> selectBlogsAsMaps();
 
+  //======================================================
+
   @Select("SELECT * FROM " +
       "blog WHERE id = #{id}")
   Blog selectBlog(int id);
 
+  //======================================================
+
   @Select("SELECT * FROM " +
       "blog WHERE id = #{id}")
   Map selectBlogAsMap(Map params);
 
+  //======================================================
+
   @Results({
       @Result(id=true,property="id",column="blog_id"),
       @Result(property="title",column="blog_title"),
-      @Result(property="author.id",column="author_id"),
-      @Result(property="author.username",column="author_username"),
-      @Result(property="author.email",column="author_email")
+      @Result(property="author", column="author_id", one = @One(
+          results = @Results({
+            @Result(id = true, property="id",column="author_id"),
+            @Result(property="username",column="author_username"),
+            @Result(property="email",column="author_email")
+              }))),
+      @Result(property="posts", column="post_id", many = @Many(
+          javaType = Post.class,
+          results = @Results({
+            @Result(id = true, property="id",column="post_id"),
+            @Result(property="subject",column="post_subject"),
+            @Result(property="body",column="post_body"),
+            @Result(property="section",column="post_section"),
+            @Result(id = true, property="author.id",column="author_id"),
+            @Result(property="author.username",column="author_username"),
+            @Result(property="author.email",column="author_email"),
+            @Result(property="createdOn",column="post_created_on")
+            ,@Result(property="tags",column="tag_id",many = @Many(
+                javaType = Tag.class,
+                results = @Results({
+                  @Result(id = true, property="id",column="tag_id"),
+                  @Result(property="name",column="tag_name")
+                    })))
+            ,@Result(property="comments",column="comment_id",many = @Many(
+                javaType = Comment.class,
+                results = @Results({
+                  @Result(id = true, property="id",column="comment_id"),
+                  @Result(property="name",column="comment_name"),
+                  @Result(property="comment",column="comment_text")
+                    })))
+              })))
       })
   @Select("select" +
       "    B.id as blog_id," +
@@ -68,4 +106,6 @@
       "    where B.id = #{id}")
   List<Blog> selectBlogWithAssociations(int id);
 
+  //======================================================
+
 }

Modified: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/test/java/org/apache/ibatis/binding/IbatisConfig.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/test/java/org/apache/ibatis/binding/IbatisConfig.java?rev=749075&r1=749074&r2=749075&view=diff
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/test/java/org/apache/ibatis/binding/IbatisConfig.java (original)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/test/java/org/apache/ibatis/binding/IbatisConfig.java Sun Mar  1 19:06:55 2009
@@ -14,6 +14,8 @@
   public static SqlSessionFactory getSqlSessionFactory() {
     try {
       DataSource dataSource = BaseDataTest.createBlogDataSource();
+      BaseDataTest.runScript(dataSource, BaseDataTest.BLOG_DDL);
+      BaseDataTest.runScript(dataSource, BaseDataTest.BLOG_DATA);
       TransactionFactory transactionFactory = new JdbcTransactionFactory();
       Environment environment = new Environment("Production", transactionFactory, dataSource);
       Configuration configuration = new Configuration(environment);