For your enjoyment here is how I solved the N+1 problem before I turned to iBatis.  I'm know that I'm opening myself to major code ridicule. 
 
Mark

 /**
  * Translates a List of maps into a normailzed structure.  Choose any number
  * of column names and pass them in as an array.  The result will be an object
  * graph grouped in the same order as the order of the column names passed in.
  * Each parent is a map with an element called "child" that holds a List of
  * Maps which in turn have their own child list. An added feature is that the
  * root holds the sum of its children on each level in a key called
  * 'numChildLevels*'.  Just substitute an integer for the *.
  *
  * This is most often used for reports.  This allow you to get all the data
  * with one call and then create the structure you need.  This saves
  * potentially hundreds of database calls while recursing.
  */
  public static List normalizeListOfMaps(List dataList, String[] colHeaders){
   
   List focus = null;
   List lastRowVals = new ArrayList( colHeaders.length);
   List childList = null;
   Map currRow = null;
   Map lastRow = null;
   Map rootMap = null;
   int n = 0;
   String key = null;
   String curr = null;
   String last = null;
   
   // The focus holds a reference to the active parent at each level.
   List[] focusLevel = new List[colHeaders.length];
   focusLevel[0] = new ArrayList();
   
   Iterator i = dataList.iterator();
   while (i.hasNext()) {
     currRow= (Map) i.next();

     for (n = 0; n < colHeaders.length; n++) {
             
       key = (String) colHeaders[n];
      
       curr = (String) currRow.get(key);
       if (lastRow != null)
         last = (String) lastRow.get(key);

     if (last == null || !curr.equals(last)) {

      if (n == 0) {
         rootMap = currRow;
      }
      
      focus = focusLevel[n];
      focus.add(currRow);
     
      // Keep a sum of all the levels in each root record.
      Integer sum = (Integer) rootMap.get("numChildLevels" + (n));
     if (sum != null)
      rootMap.put("numChildLevels" + (n), new Integer(sum.intValue() + 1));
     else
      rootMap.put("numChildLevels" + (n), new Integer(1));

      // When not a leaf node.
      if (n < colHeaders.length - 1) {
        childList = new ArrayList();
        focusLevel[n+1] = childList;
        currRow.put("child",childList);
          // Create a copy so it can have its own child pointer.
          currRow = new HashMap(currRow);
      }
     }
    }
     lastRow = currRow;
   }
   
   return focusLevel[0];
  }

 

Reply via email to