Coverage Report - org.apache.commons.scaffold.sql.ResultSetUtils
 
Classes in this File Line Coverage Branch Coverage Complexity
ResultSetUtils
0%
0/99
0%
0/55
7.833
 
 1  
  /*
 2  
  * Copyright 2001,2004 The Apache Software Foundation.
 3  
  * 
 4  
  * Licensed under the Apache License, Version 2.0 (the "License");
 5  
  * you may not use this file except in compliance with the License.
 6  
  * You may obtain a copy of the License at
 7  
  * 
 8  
  *      http://www.apache.org/licenses/LICENSE-2.0
 9  
  * 
 10  
  * Unless required by applicable law or agreed to in writing, software
 11  
  * distributed under the License is distributed on an "AS IS" BASIS,
 12  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13  
  * See the License for the specific language governing permissions and
 14  
  * limitations under the License.
 15  
  */
 16  
 
 17  
 package org.apache.commons.scaffold.sql;
 18  
 
 19  
 
 20  
 import java.beans.PropertyDescriptor;
 21  
 import java.lang.reflect.InvocationTargetException;
 22  
 import java.lang.reflect.Method;
 23  
 import java.sql.ResultSet;
 24  
 import java.sql.ResultSetMetaData;
 25  
 import java.sql.SQLException;
 26  
 import java.sql.Types;
 27  
 import java.util.ArrayList;
 28  
 import java.util.Collection;
 29  
 import java.util.HashMap;
 30  
 import java.util.Iterator;
 31  
 import java.util.Map;
 32  
 
 33  
 import org.apache.commons.beanutils.BeanUtils;
 34  
 import org.apache.commons.beanutils.PropertyUtils;
 35  
 
 36  
 
 37  
  /**
 38  
   * General purpose utility methods related to ResultSets
 39  
   *
 40  
   * @author Ted Husted
 41  
   * @version $Revision: 561366 $ $Date: 2007-07-31 16:58:29 +0100 (Tue, 31 Jul 2007) $
 42  
   */
 43  0
  public class ResultSetUtils {
 44  
 
 45  
 
 46  
      /**
 47  
       * Returns next record of result set as a Map.
 48  
       * The keys of the map are the column names,
 49  
       * as returned by the metadata.
 50  
       * The values are the columns as Objects.
 51  
       *
 52  
       * @param resultSet The ResultSet to process.
 53  
       * @exception SQLException if an error occurs.
 54  
       */
 55  
      public static Map getMap(ResultSet resultSet)
 56  
         throws SQLException {
 57  
 
 58  
             // Acquire resultSet MetaData
 59  0
         ResultSetMetaData metaData = resultSet.getMetaData();
 60  0
         int cols = metaData.getColumnCount();
 61  
 
 62  
             // Create hashmap, sized to number of columns
 63  0
         HashMap row = new HashMap(cols,1);
 64  
 
 65  
             // Transfer record into hashmap
 66  0
         if (resultSet.next()) {
 67  0
             for (int i=1; i<=cols ; i++) {
 68  0
                 row.put(metaData.getColumnName(i),
 69  
                     resultSet.getObject(i));
 70  
             }
 71  
         } // end while
 72  
 
 73  0
         return ((Map) row);
 74  
 
 75  
      } // end getMap
 76  
 
 77  
 
 78  
      /**
 79  
       * Return a Collection of Maps, each representing
 80  
       * a row from the ResultSet.
 81  
       * The keys of the map are the column names,
 82  
       * as returned by the metadata.
 83  
       * The values are the columns as Objects.
 84  
       *
 85  
       * @param resultSet The ResultSet to process.
 86  
       * @exception SQLException if an error occurs.
 87  
       */
 88  
      public static Collection getMaps(ResultSet resultSet)
 89  
         throws SQLException {
 90  
 
 91  
             // Acquire resultSet MetaData
 92  0
         ResultSetMetaData metaData = resultSet.getMetaData();
 93  0
         int cols = metaData.getColumnCount();
 94  
 
 95  
             // Use ArrayList to maintain ResultSet sequence
 96  0
         ArrayList list = new ArrayList();
 97  
 
 98  
             // Scroll to each record, make map of row, add to list
 99  0
         while (resultSet.next()) {
 100  0
             HashMap row = new HashMap(cols,1);
 101  0
             for (int i=1; i<=cols ; i++) {
 102  0
                 row.put(metaData.getColumnName(i),
 103  
                     resultSet.getString(i));
 104  
             }
 105  0
             list.add(row);
 106  0
         } // end while
 107  
 
 108  0
         return ((Collection) list);
 109  
 
 110  
      } // end getMaps
 111  
 
 112  
 
 113  
     /**
 114  
      * Populate the JavaBean properties of the specified bean, based on
 115  
      * the specified name/value pairs.  This method uses Java reflection APIs
 116  
      * to identify corresponding "property setter" method names. The type of
 117  
      * the value in the Map must match the setter type. The setter must
 118  
      * expect a single arguement (the one on the Map).
 119  
      * <p>
 120  
      * The particular setter method to be called for each property is
 121  
      * determined using the usual JavaBeans introspection mechanisms. Thus,
 122  
      * you may identify custom setter methods using a BeanInfo class that is
 123  
      * associated with the class of the bean itself. If no such BeanInfo
 124  
      * class is available, the standard method name conversion ("set" plus
 125  
      * the capitalized name of the property in question) is used.
 126  
      * <p>
 127  
      * <strong>NOTE</strong>:  It is contrary to the JavaBeans Specification
 128  
      * to have more than one setter method (with different argument
 129  
      * signatures) for the same property.
 130  
      * <p>
 131  
      * This method adopted from the Apache Commons BeanUtils.populate.
 132  
      *
 133  
      * @author Craig R. McClanahan
 134  
      * @author Ralph Schaer
 135  
      * @author Chris Audley
 136  
      * @author Rey Fran�ois
 137  
      * @author Gregor Ra�man
 138  
      * @author Ted Husted
 139  
      *
 140  
      * @param bean JavaBean whose properties are being populated
 141  
      * @param properties Map keyed by property name, with the
 142  
      *  corresponding value to be set
 143  
      *
 144  
      * @exception IllegalAccessException if the caller does not have
 145  
      *  access to the property accessor method
 146  
      * @exception InvocationTargetException if the property accessor method
 147  
      *  throws an exception
 148  
      * @deprecated Use BeanUtils.CopyProperties instead.
 149  
      */
 150  
     public static void setProperties(Object bean, Map properties)
 151  
         throws IllegalAccessException, InvocationTargetException {
 152  
 
 153  0
         if ((bean == null) || (properties == null))
 154  0
             return;
 155  
 
 156  
         /*
 157  
         if (debug >= 1)
 158  
             System.out.println("BeanUtils.populate(" + bean + ", " +
 159  
                                properties + ")");
 160  
         */
 161  
 
 162  
         // Loop through the property name/value pairs to be set
 163  0
         Iterator names = properties.keySet().iterator();
 164  0
         while (names.hasNext()) {
 165  
 
 166  
             // Identify the property name and value(s) to be assigned
 167  0
             String name = (String) names.next();
 168  0
             if (name == null)
 169  0
                 continue;
 170  
 
 171  
             // Get the property descriptor of the requested property (if any)
 172  0
             PropertyDescriptor descriptor = null;
 173  
             try {
 174  0
                 descriptor = PropertyUtils.getPropertyDescriptor(bean, name);
 175  0
             } catch (Throwable t) {
 176  
                 /*
 177  
                 if (debug >= 1)
 178  
                     System.out.println("    getPropertyDescriptor: " + t);
 179  
                 */
 180  0
                 descriptor = null;
 181  0
             }
 182  0
             if (descriptor == null) {
 183  
                 /*
 184  
                 if (debug >= 1)
 185  
                     System.out.println("    No such property, skipping");
 186  
                 */
 187  0
                 continue;
 188  
             }
 189  
 
 190  
             /*
 191  
             if (debug >= 1)
 192  
                 System.out.println("    Property descriptor is '" +
 193  
                                    descriptor + "'");
 194  
             */
 195  
 
 196  
             // Identify the relevant setter method (if there is one)
 197  0
             Method setter = descriptor.getWriteMethod();
 198  0
             if (setter == null) {
 199  
                 /*
 200  
                 if (debug >= 1)
 201  
                     System.out.println("    No setter method, skipping");
 202  
                 */
 203  0
                 continue;
 204  
             }
 205  
 
 206  
             // Obtain value to be set
 207  0
             Object[] args = new Object[1];
 208  0
             args[0] = properties.get(name); // This MUST match setter type
 209  
 
 210  
             /*
 211  
             if (debug >= 1)
 212  
                 System.out.println("  name='" + name + "', value.class='" +
 213  
                                    (value == null ? "NONE" :
 214  
                                    value.getClass().getName()) + "'");
 215  
             */
 216  
             /*
 217  
             if (debug >= 1)
 218  
                 System.out.println("    Setting to " +
 219  
                                    (parameters[0] == null ? "NULL" :
 220  
                                     "'" + parameters[0] + "'"));
 221  
             */
 222  
 
 223  
             // Invoke the setter method
 224  0
             setter.invoke(bean,args);
 225  0
         }
 226  
 
 227  
         /*
 228  
         if (debug >= 1)
 229  
             System.out.println("============================================");
 230  
         */
 231  
 
 232  0
     } // end setProperties
 233  
 
 234  
 
 235  
     /**
 236  
      * Map JDBC objects to Java equivalents.
 237  
      * Used by getBean() and getBeans().
 238  
      * <p>
 239  
      * Some types not supported.
 240  
      * Many not work with all drivers.
 241  
      * <p>
 242  
      * Makes binary conversions of BIGINT, DATE, DECIMAL, DOUBLE, FLOAT, INTEGER,
 243  
      * REAL, SMALLINT, TIME, TIMESTAMP, TINYINT.
 244  
      * Makes Sting conversions of CHAR, CLOB, VARCHAR, LONGVARCHAR, BLOB, LONGVARBINARY,
 245  
      * VARBINARY.
 246  
      * <p>
 247  
      * DECIMAL, INTEGER, SMALLINT, TIMESTAMP, CHAR, VARCHAR tested with MySQL and Poolman.
 248  
      * Others not guaranteed.
 249  
      */
 250  
     public static void putEntry(
 251  
             Map properties,
 252  
             ResultSetMetaData metaData,
 253  
             ResultSet resultSet,
 254  
             int i)
 255  
         throws SQLException {
 256  
 
 257  
         /*
 258  
         In a perfect universe, this would be enough
 259  
             properties.put(
 260  
                 metaData.getColumnName(i),
 261  
                 resultSet.getObject(i));
 262  
         But only String, Timestamp, and Integer seem to get through that way.
 263  
         */
 264  
 
 265  0
         String columnName = metaData.getColumnName(i);
 266  
 
 267  0
         switch (metaData.getColumnType(i)) {
 268  
 
 269  
             // http://java.sun.com/j2se/1.3.0/docs/api/java/sql/Types.html
 270  
 
 271  
             case Types.BIGINT:
 272  0
                 properties.put(columnName,
 273  
                     new Long(resultSet.getLong(i)));
 274  0
                 break;
 275  
 
 276  
             case Types.DATE:
 277  0
                 properties.put(columnName,
 278  
                     resultSet.getDate(i));
 279  0
                 break;
 280  
 
 281  
             case Types.DECIMAL:
 282  
             case Types.DOUBLE:
 283  0
                 properties.put(columnName,
 284  
                     new Double(resultSet.getDouble(i)));
 285  0
                 break;
 286  
 
 287  
             case Types.FLOAT:
 288  0
                 properties.put(columnName,
 289  
                     new Float(resultSet.getFloat(i)));
 290  0
                 break;
 291  
 
 292  
             case Types.INTEGER:
 293  0
                 properties.put(columnName,
 294  
                     new Integer(resultSet.getInt(i)));
 295  0
                 break;
 296  
 
 297  
             case Types.REAL:
 298  0
                 properties.put(columnName,
 299  
                     new Double(resultSet.getString(i)));
 300  0
                 break;
 301  
 
 302  
             case Types.SMALLINT:
 303  0
                 properties.put(columnName,
 304  
                     new Short(resultSet.getShort(i)));
 305  0
                 break;
 306  
 
 307  
             case Types.TIME:
 308  0
                 properties.put(columnName,
 309  
                     resultSet.getTime(i));
 310  0
                 break;
 311  
 
 312  
             case Types.TIMESTAMP:
 313  0
                 properties.put(columnName,
 314  
                     resultSet.getTimestamp(i));
 315  0
                 break;
 316  
 
 317  
             // :FIXME: Throws java.lang.ClassCastException: java.lang.Integer
 318  
             // :FIXME: with Poolman and MySQL unless use getString.
 319  
             case Types.TINYINT:
 320  0
                 properties.put(columnName,
 321  
                     new Byte(resultSet.getString(i)));
 322  0
                 break;
 323  
 
 324  
             case Types.CHAR:
 325  
             case Types.CLOB:
 326  
             case Types.VARCHAR:
 327  
             case Types.LONGVARCHAR:
 328  
                 // :FIXME: Handle binaries differently?
 329  
             case Types.BLOB:
 330  
             case Types.LONGVARBINARY:
 331  
             case Types.VARBINARY:
 332  0
                 properties.put(columnName,
 333  
                     resultSet.getString(i));
 334  0
                break;
 335  
 
 336  
             /*
 337  
                 :FIXME: Add handlers for
 338  
                 ARRAY
 339  
                 BINARY
 340  
                 BIT
 341  
                 DISTINCT
 342  
                 JAVA_OBJECT
 343  
                 NULL
 344  
                 NUMERIC
 345  
                 OTHER
 346  
                 REF
 347  
                 STRUCT
 348  
             */
 349  
 
 350  
              // Otherwise, pass as *String property to be converted
 351  
             default:
 352  0
                 properties.put(columnName + "String",
 353  
                     resultSet.getString(i));
 354  
                 break;
 355  
         } // end switch
 356  
 
 357  0
     } // end putEntry
 358  
 
 359  
 
 360  
     /**
 361  
      * Populate target bean with the first record from a ResultSet.
 362  
      *
 363  
      * @param resultSet The ResultSet whose parameters are to be used
 364  
      * to populate bean properties
 365  
      * @param target An instance of the bean to populate
 366  
      * @exception SQLException if an exception is thrown while setting
 367  
      * property values, populating the bean, or accessing the ResultSet
 368  
      * @return True if resultSet contained a next element
 369  
      */
 370  
     public static boolean getElement(Object target, ResultSet resultSet)
 371  
         throws SQLException {
 372  
 
 373  
             // Check prerequisites
 374  0
         if ((target==null) || (resultSet==null))
 375  0
             throw new SQLException("getElement: Null parameter");
 376  
 
 377  
             // Acquire resultSet MetaData
 378  0
         ResultSetMetaData metaData = resultSet.getMetaData();
 379  0
         int cols = metaData.getColumnCount();
 380  
 
 381  
             // Create hashmap, sized to number of columns
 382  0
         HashMap properties = new HashMap(cols,1);
 383  
 
 384  
             // Scroll to next record and pump into hashmap
 385  0
         boolean found = false;
 386  0
         if (resultSet.next()) {
 387  0
             found = true;
 388  0
             for (int i=1; i<=cols ; i++) {
 389  0
                 putEntry(properties,metaData,resultSet,i);
 390  
             }
 391  
             try {
 392  0
                 BeanUtils.copyProperties(target,properties);
 393  
             }
 394  0
             catch (Throwable t) {
 395  0
                 throw new SQLException("ResultSetUtils.getElement: " +
 396  
                     t.getMessage() + properties.toString());
 397  0
             }
 398  
 
 399  
         } // end if
 400  
 
 401  0
         return found;
 402  
 
 403  
      } // end getElement
 404  
 
 405  
 
 406  
     /**
 407  
      * Return a ArrayList of beans populated from a ResultSet.
 408  
      *
 409  
      * @param resultSet The ResultSet whose parameters are to be used
 410  
      * to populate bean properties
 411  
      * @param target An instance of the bean to populate
 412  
      * @exception SQLException if an exception is thrown while setting
 413  
      * property values, populating the bean, or accessing the ResultSet
 414  
      */
 415  
      public static Collection getCollection(Object target, ResultSet resultSet)
 416  
         throws SQLException {
 417  
 
 418  
             // Check prerequisites
 419  0
         if ((target==null) || (resultSet==null))
 420  0
             throw new SQLException("getCollection: Null parameter");
 421  
 
 422  
             // Acquire resultSet MetaData
 423  0
         ResultSetMetaData metaData = resultSet.getMetaData();
 424  0
         int cols = metaData.getColumnCount();
 425  
 
 426  
             // Create hashmap, sized to number of columns
 427  0
         HashMap properties = new HashMap(cols,1);
 428  
 
 429  
             // Use ArrayList to maintain ResultSet sequence
 430  0
         ArrayList list = new ArrayList();
 431  
 
 432  
             // Acquire target class
 433  0
         Class factory = target.getClass();
 434  
 
 435  
             // Scroll to next record and pump into hashmap
 436  0
         while (resultSet.next()) {
 437  0
             for (int i=1; i<=cols ; i++) {
 438  0
                 putEntry(properties,metaData,resultSet,i);
 439  
             }
 440  
             try {
 441  0
                 Object bean = factory.newInstance();
 442  0
                 BeanUtils.copyProperties(bean,properties);
 443  0
                 list.add(bean);
 444  
             }
 445  0
             catch (Throwable t) {
 446  0
                 throw new SQLException("RequestUtils.getCollection: " +
 447  
                     t.getMessage());
 448  0
             }
 449  
 
 450  0
             properties.clear();
 451  
 
 452  
         } // end while
 453  
 
 454  0
         return ((Collection) list);
 455  
 
 456  
      } // end getCollection
 457  
 
 458  
 
 459  
 } // end ResultSetUtils
 460