Mega Code Archive

 
Categories / Java / Database SQL JDBC
 

Wraps a ResultSet in an Iterator

import java.beans.BeanInfo; import java.beans.IntrospectionException; import java.beans.Introspector; import java.beans.PropertyDescriptor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.sql.Timestamp; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; /**  * <p>  * Wraps a <code>ResultSet</code> in an <code>Iterator</code>.  This is useful  * when you want to present a non-database application layer with domain  * neutral data.  * </p>  *   * <p>  * This implementation requires the <code>ResultSet.isLast()</code> method  * to be implemented.  * </p>  */ public class ResultSetIterator implements Iterator {     /**      * The wrapped <code>ResultSet</code>.      */     private final ResultSet rs;          /**      * The processor to use when converting a row into an Object[].      */     private final RowProcessor convert;     /**      * Constructor for ResultSetIterator.      * @param rs Wrap this <code>ResultSet</code> in an <code>Iterator</code>.      */     public ResultSetIterator(ResultSet rs) {         this(rs , new BasicRowProcessor());     }          /**      * Constructor for ResultSetIterator.      * @param rs Wrap this <code>ResultSet</code> in an <code>Iterator</code>.      * @param convert The processor to use when converting a row into an       * <code>Object[]</code>.  Defaults to a       * <code>BasicRowProcessor</code>.      */     public ResultSetIterator(ResultSet rs, RowProcessor convert) {         this.rs = rs;         this.convert = convert;     }     /**      * Returns true if there are more rows in the ResultSet.      * @return boolean <code>true</code> if there are more rows      * @throws RuntimeException if an SQLException occurs.      */     public boolean hasNext() {         try {             return !rs.isLast();         } catch (SQLException e) {             rethrow(e);             return false;         }     }     /**      * Returns the next row as an <code>Object[]</code>.      * @return An <code>Object[]</code> with the same number of elements as      * columns in the <code>ResultSet</code>.       * @see java.util.Iterator#next()      * @throws RuntimeException if an SQLException occurs.      */     public Object next() {         try {             rs.next();             return this.convert.toArray(rs);         } catch (SQLException e) {             rethrow(e);             return null;         }     }     /**      * Deletes the current row from the <code>ResultSet</code>.      * @see java.util.Iterator#remove()      * @throws RuntimeException if an SQLException occurs.      */     public void remove() {         try {             this.rs.deleteRow();         } catch (SQLException e) {             rethrow(e);         }     }     /**      * Rethrow the SQLException as a RuntimeException.  This implementation      * creates a new RuntimeException with the SQLException's error message.      * @param e SQLException to rethrow      * @since DbUtils 1.1      */     protected void rethrow(SQLException e) {         throw new RuntimeException(e.getMessage());     } } /**  * <code>RowProcessor</code> implementations convert   * <code>ResultSet</code> rows into various other objects.  Implementations  * can extend <code>BasicRowProcessor</code> to protect themselves  * from changes to this interface.   *   * @see BasicRowProcessor  */  interface RowProcessor {     /**      * Create an <code>Object[]</code> from the column values in one       * <code>ResultSet</code> row.  The <code>ResultSet</code> should be       * positioned on a valid row before passing it to this method.        * Implementations of this method must not alter the row position of       * the <code>ResultSet</code>.       *      * @param rs ResultSet that supplies the array data      * @throws SQLException if a database access error occurs      * @return the newly created array      */     public Object[] toArray(ResultSet rs) throws SQLException;     /**      * Create a JavaBean from the column values in one <code>ResultSet</code>       * row.  The <code>ResultSet</code> should be positioned on a valid row before      * passing it to this method.  Implementations of this method must not      * alter the row position of the <code>ResultSet</code>.      *      * @param rs ResultSet that supplies the bean data      * @param type Class from which to create the bean instance      * @throws SQLException if a database access error occurs      * @return the newly created bean      */     public Object toBean(ResultSet rs, Class type) throws SQLException;     /**      * Create a <code>List</code> of JavaBeans from the column values in all       * <code>ResultSet</code> rows.  <code>ResultSet.next()</code> should       * <strong>not</strong> be called before passing it to this method.      *       * @param rs ResultSet that supplies the bean data      * @param type Class from which to create the bean instance      * @throws SQLException if a database access error occurs      * @return A <code>List</code> of beans with the given type in the order       * they were returned by the <code>ResultSet</code>.      */     public List toBeanList(ResultSet rs, Class type) throws SQLException;     /**      * Create a <code>Map</code> from the column values in one       * <code>ResultSet</code> row.  The <code>ResultSet</code> should be       * positioned on a valid row before      * passing it to this method.  Implementations of this method must not      * alter the row position of the <code>ResultSet</code>.      *      * @param rs ResultSet that supplies the map data      * @throws SQLException if a database access error occurs      * @return the newly created Map      */     public Map toMap(ResultSet rs) throws SQLException; }  /*   * Licensed to the Apache Software Foundation (ASF) under one or more   * contributor license agreements.  See the NOTICE file distributed with   * this work for additional information regarding copyright ownership.   * The ASF licenses this file to You under the Apache License, Version 2.0   * (the "License"); you may not use this file except in compliance with   * the License.  You may obtain a copy of the License at   *   *      http://www.apache.org/licenses/LICENSE-2.0   *   * Unless required by applicable law or agreed to in writing, software   * distributed under the License is distributed on an "AS IS" BASIS,   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   * See the License for the specific language governing permissions and   * limitations under the License.   */  /**   * Basic implementation of the <code>RowProcessor</code> interface.   *    * <p>   * This class is thread-safe.   * </p>   *    * @see RowProcessor   */  class BasicRowProcessor implements RowProcessor {      /**       * The default BeanProcessor instance to use if not supplied in the       * constructor.       */      private static final BeanProcessor defaultConvert = new BeanProcessor();      /**       * The Singleton instance of this class.       */      private static final BasicRowProcessor instance = new BasicRowProcessor();      /**       * Returns the Singleton instance of this class.       *       * @return The single instance of this class.       * @deprecated Create instances with the constructors instead.  This will        * be removed after DbUtils 1.1.       */      public static BasicRowProcessor instance() {          return instance;      }      /**       * Use this to process beans.       */      private final BeanProcessor convert;      /**       * BasicRowProcessor constructor.  Bean processing defaults to a        * BeanProcessor instance.       */      public BasicRowProcessor() {          this(defaultConvert);      }            /**       * BasicRowProcessor constructor.       * @param convert The BeanProcessor to use when converting columns to        * bean properties.       * @since DbUtils 1.1       */      public BasicRowProcessor(BeanProcessor convert) {          super();          this.convert = convert;      }      /**       * Convert a <code>ResultSet</code> row into an <code>Object[]</code>.       * This implementation copies column values into the array in the same        * order they're returned from the <code>ResultSet</code>.  Array elements       * will be set to <code>null</code> if the column was SQL NULL.       *       * @see org.apache.commons.dbutils.RowProcessor#toArray(java.sql.ResultSet)       */      public Object[] toArray(ResultSet rs) throws SQLException {          ResultSetMetaData meta = rs.getMetaData();          int cols = meta.getColumnCount();          Object[] result = new Object[cols];          for (int i = 0; i < cols; i++) {              result[i] = rs.getObject(i + 1);          }          return result;      }      /**       * Convert a <code>ResultSet</code> row into a JavaBean.  This        * implementation delegates to a BeanProcessor instance.       * @see org.apache.commons.dbutils.RowProcessor#toBean(java.sql.ResultSet, java.lang.Class)       * @see org.apache.commons.dbutils.BeanProcessor#toBean(java.sql.ResultSet, java.lang.Class)        */      public Object toBean(ResultSet rs, Class type) throws SQLException {          return this.convert.toBean(rs, type);      }      /**       * Convert a <code>ResultSet</code> into a <code>List</code> of JavaBeans.         * This implementation delegates to a BeanProcessor instance.        * @see org.apache.commons.dbutils.RowProcessor#toBeanList(java.sql.ResultSet, java.lang.Class)       * @see org.apache.commons.dbutils.BeanProcessor#toBeanList(java.sql.ResultSet, java.lang.Class)       */      public List toBeanList(ResultSet rs, Class type) throws SQLException {          return this.convert.toBeanList(rs, type);      }      /**       * Convert a <code>ResultSet</code> row into a <code>Map</code>.  This        * implementation returns a <code>Map</code> with case insensitive column       * names as keys.  Calls to <code>map.get("COL")</code> and        * <code>map.get("col")</code> return the same value.       * @see org.apache.commons.dbutils.RowProcessor#toMap(java.sql.ResultSet)       */      public Map toMap(ResultSet rs) throws SQLException {          Map result = new CaseInsensitiveHashMap();          ResultSetMetaData rsmd = rs.getMetaData();          int cols = rsmd.getColumnCount();          for (int i = 1; i <= cols; i++) {              result.put(rsmd.getColumnName(i), rs.getObject(i));          }          return result;      }            /**       * A Map that converts all keys to lowercase Strings for case insensitive       * lookups.  This is needed for the toMap() implementation because        * databases don't consistenly handle the casing of column names.        *        * <p>The keys are stored as they are given [BUG #DBUTILS-34], so we maintain       * an internal mapping from lowercase keys to the real keys in order to        * achieve the case insensitive lookup.       *        * <p>Note: This implementation does not allow <tt>null</tt>       * for key, whereas {@link HashMap} does, because of the code:       * <pre>       * key.toString().toLowerCase()       * </pre>       */      private static class CaseInsensitiveHashMap extends HashMap {          /**           * The internal mapping from lowercase keys to the real keys.           *            * <p>           * Any query operation using the key            * ({@link #get(Object)}, {@link #containsKey(Object)})           * is done in three steps:           * <ul>           * <li>convert the parameter key to lower case</li>           * <li>get the actual key that corresponds to the lower case key</li>           * <li>query the map with the actual key</li>           * </ul>           * </p>           */          private final Map lowerCaseMap = new HashMap();          /**           * Required for serialization support.           *            * @see java.io.Serializable           */           private static final long serialVersionUID = 1841673097701957808L;          /**           * @see java.util.Map#containsKey(java.lang.Object)           */          public boolean containsKey(Object key) {              Object realKey = lowerCaseMap.get(key.toString().toLowerCase());              return super.containsKey(realKey);              // Possible optimisation here:              // Since the lowerCaseMap contains a mapping for all the keys,              // we could just do this:              // return lowerCaseMap.containsKey(key.toString().toLowerCase());          }          /**           * @see java.util.Map#get(java.lang.Object)           */          public Object get(Object key) {              Object realKey = lowerCaseMap.get(key.toString().toLowerCase());              return super.get(realKey);          }          /**           * @see java.util.Map#put(java.lang.Object, java.lang.Object)           */          public Object put(Object key, Object value) {              /*               * In order to keep the map and lowerCaseMap synchronized,               * we have to remove the old mapping before putting the                * new one. Indeed, oldKey and key are not necessaliry equals.               * (That's why we call super.remove(oldKey) and not just               * super.put(key, value))               */              Object oldKey = lowerCaseMap.put(key.toString().toLowerCase(), key);              Object oldValue = super.remove(oldKey);              super.put(key, value);              return oldValue;          }          /**           * @see java.util.Map#putAll(java.util.Map)           */          public void putAll(Map m) {              Iterator iter = m.entrySet().iterator();              while (iter.hasNext()) {                  Map.Entry entry = (Map.Entry) iter.next();                  Object key = entry.getKey();                  Object value = entry.getValue();                  this.put(key, value);              }          }          /**           * @see java.util.Map#remove(java.lang.Object)           */          public Object remove(Object key) {              Object realKey = lowerCaseMap.remove(key.toString().toLowerCase());              return super.remove(realKey);          }      }        }  /*   * Licensed to the Apache Software Foundation (ASF) under one or more   * contributor license agreements.  See the NOTICE file distributed with   * this work for additional information regarding copyright ownership.   * The ASF licenses this file to You under the Apache License, Version 2.0   * (the "License"); you may not use this file except in compliance with   * the License.  You may obtain a copy of the License at   *   *      http://www.apache.org/licenses/LICENSE-2.0   *   * Unless required by applicable law or agreed to in writing, software   * distributed under the License is distributed on an "AS IS" BASIS,   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   * See the License for the specific language governing permissions and   * limitations under the License.   */  /**   * <p>   * <code>BeanProcessor</code> matches column names to bean property names    * and converts <code>ResultSet</code> columns into objects for those bean    * properties.  Subclasses should override the methods in the processing chain   * to customize behavior.   * </p>   *    * <p>   * This class is thread-safe.   * </p>   *    * @see BasicRowProcessor   *    * @since DbUtils 1.1   */   class BeanProcessor {      /**       * Special array value used by <code>mapColumnsToProperties</code> that        * indicates there is no bean property that matches a column from a        * <code>ResultSet</code>.       */      protected static final int PROPERTY_NOT_FOUND = -1;      /**       * Set a bean's primitive properties to these defaults when SQL NULL        * is returned.  These are the same as the defaults that ResultSet get*        * methods return in the event of a NULL column.       */      private static final Map primitiveDefaults = new HashMap();      static {          primitiveDefaults.put(Integer.TYPE, new Integer(0));          primitiveDefaults.put(Short.TYPE, new Short((short) 0));          primitiveDefaults.put(Byte.TYPE, new Byte((byte) 0));          primitiveDefaults.put(Float.TYPE, new Float(0));          primitiveDefaults.put(Double.TYPE, new Double(0));          primitiveDefaults.put(Long.TYPE, new Long(0));          primitiveDefaults.put(Boolean.TYPE, Boolean.FALSE);          primitiveDefaults.put(Character.TYPE, new Character('\u0000'));      }      /**       * Constructor for BeanProcessor.       */      public BeanProcessor() {          super();      }      /**       * Convert a <code>ResultSet</code> row into a JavaBean.  This        * implementation uses reflection and <code>BeanInfo</code> classes to        * match column names to bean property names.  Properties are matched to        * columns based on several factors:       * <br/>       * <ol>       *     <li>       *     The class has a writable property with the same name as a column.       *     The name comparison is case insensitive.       *     </li>       *        *     <li>       *     The column type can be converted to the property's set method        *     parameter type with a ResultSet.get* method.  If the conversion fails       *     (ie. the property was an int and the column was a Timestamp) an       *     SQLException is thrown.       *     </li>       * </ol>       *        * <p>       * Primitive bean properties are set to their defaults when SQL NULL is       * returned from the <code>ResultSet</code>.  Numeric fields are set to 0       * and booleans are set to false.  Object bean properties are set to        * <code>null</code> when SQL NULL is returned.  This is the same behavior       * as the <code>ResultSet</code> get* methods.       * </p>       *       * @param rs ResultSet that supplies the bean data       * @param type Class from which to create the bean instance       * @throws SQLException if a database access error occurs       * @return the newly created bean       */      public Object toBean(ResultSet rs, Class type) throws SQLException {          PropertyDescriptor[] props = this.propertyDescriptors(type);          ResultSetMetaData rsmd = rs.getMetaData();          int[] columnToProperty = this.mapColumnsToProperties(rsmd, props);          return this.createBean(rs, type, props, columnToProperty);      }      /**       * Convert a <code>ResultSet</code> into a <code>List</code> of JavaBeans.         * This implementation uses reflection and <code>BeanInfo</code> classes to        * match column names to bean property names. Properties are matched to        * columns based on several factors:       * <br/>       * <ol>       *     <li>       *     The class has a writable property with the same name as a column.       *     The name comparison is case insensitive.       *     </li>       *        *     <li>       *     The column type can be converted to the property's set method        *     parameter type with a ResultSet.get* method.  If the conversion fails       *     (ie. the property was an int and the column was a Timestamp) an       *     SQLException is thrown.       *     </li>       * </ol>       *        * <p>       * Primitive bean properties are set to their defaults when SQL NULL is       * returned from the <code>ResultSet</code>.  Numeric fields are set to 0       * and booleans are set to false.  Object bean properties are set to        * <code>null</code> when SQL NULL is returned.  This is the same behavior       * as the <code>ResultSet</code> get* methods.       * </p>       *       * @param rs ResultSet that supplies the bean data       * @param type Class from which to create the bean instance       * @throws SQLException if a database access error occurs       * @return the newly created List of beans       */      public List toBeanList(ResultSet rs, Class type) throws SQLException {          List results = new ArrayList();          if (!rs.next()) {              return results;          }          PropertyDescriptor[] props = this.propertyDescriptors(type);          ResultSetMetaData rsmd = rs.getMetaData();          int[] columnToProperty = this.mapColumnsToProperties(rsmd, props);          do {              results.add(this.createBean(rs, type, props, columnToProperty));          } while (rs.next());          return results;      }      /**       * Creates a new object and initializes its fields from the ResultSet.       *       * @param rs The result set.       * @param type The bean type (the return type of the object).       * @param props The property descriptors.       * @param columnToProperty The column indices in the result set.       * @return An initialized object.       * @throws SQLException if a database error occurs.       */      private Object createBean(ResultSet rs, Class type,              PropertyDescriptor[] props, int[] columnToProperty)              throws SQLException {          Object bean = this.newInstance(type);          for (int i = 1; i < columnToProperty.length; i++) {              if (columnToProperty[i] == PROPERTY_NOT_FOUND) {                  continue;              }              PropertyDescriptor prop = props[columnToProperty[i]];              Class propType = prop.getPropertyType();              Object value = this.processColumn(rs, i, propType);              if (propType != null && value == null && propType.isPrimitive()) {                  value = primitiveDefaults.get(propType);              }              this.callSetter(bean, prop, value);          }          return bean;      }      /**       * Calls the setter method on the target object for the given property.       * If no setter method exists for the property, this method does nothing.       * @param target The object to set the property on.       * @param prop The property to set.       * @param value The value to pass into the setter.       * @throws SQLException if an error occurs setting the property.       */      private void callSetter(Object target, PropertyDescriptor prop, Object value)              throws SQLException {          Method setter = prop.getWriteMethod();          if (setter == null) {              return;          }          Class[] params = setter.getParameterTypes();          try {              // convert types for some popular ones              if (value != null) {                  if (value instanceof java.util.Date) {                      if (params[0].getName().equals("java.sql.Date")) {                          value = new java.sql.Date(((java.util.Date) value).getTime());                      } else                      if (params[0].getName().equals("java.sql.Time")) {                          value = new java.sql.Time(((java.util.Date) value).getTime());                      } else                      if (params[0].getName().equals("java.sql.Timestamp")) {                          value = new java.sql.Timestamp(((java.util.Date) value).getTime());                      }                  }              }              // Don't call setter if the value object isn't the right type               if (this.isCompatibleType(value, params[0])) {                  setter.invoke(target, new Object[] { value });              } else {                throw new SQLException(                    "Cannot set " + prop.getName() + ": incompatible types.");              }          } catch (IllegalArgumentException e) {              throw new SQLException(                  "Cannot set " + prop.getName() + ": " + e.getMessage());          } catch (IllegalAccessException e) {              throw new SQLException(                  "Cannot set " + prop.getName() + ": " + e.getMessage());          } catch (InvocationTargetException e) {              throw new SQLException(                  "Cannot set " + prop.getName() + ": " + e.getMessage());          }      }      /**       * ResultSet.getObject() returns an Integer object for an INT column.  The       * setter method for the property might take an Integer or a primitive int.       * This method returns true if the value can be successfully passed into       * the setter method.  Remember, Method.invoke() handles the unwrapping       * of Integer into an int.       *        * @param value The value to be passed into the setter method.       * @param type The setter's parameter type.       * @return boolean True if the value is compatible.       */      private boolean isCompatibleType(Object value, Class type) {          // Do object check first, then primitives          if (value == null || type.isInstance(value)) {              return true;          } else if (              type.equals(Integer.TYPE) && Integer.class.isInstance(value)) {              return true;          } else if (type.equals(Long.TYPE) && Long.class.isInstance(value)) {              return true;          } else if (              type.equals(Double.TYPE) && Double.class.isInstance(value)) {              return true;          } else if (type.equals(Float.TYPE) && Float.class.isInstance(value)) {              return true;          } else if (type.equals(Short.TYPE) && Short.class.isInstance(value)) {              return true;          } else if (type.equals(Byte.TYPE) && Byte.class.isInstance(value)) {              return true;          } else if (              type.equals(Character.TYPE) && Character.class.isInstance(value)) {              return true;          } else if (              type.equals(Boolean.TYPE) && Boolean.class.isInstance(value)) {              return true;          } else {              return false;          }      }      /**       * Factory method that returns a new instance of the given Class.  This       * is called at the start of the bean creation process and may be        * overridden to provide custom behavior like returning a cached bean       * instance.       *       * @param c The Class to create an object from.       * @return A newly created object of the Class.       * @throws SQLException if creation failed.       */      protected Object newInstance(Class c) throws SQLException {          try {              return c.newInstance();          } catch (InstantiationException e) {              throw new SQLException(                  "Cannot create " + c.getName() + ": " + e.getMessage());          } catch (IllegalAccessException e) {              throw new SQLException(                  "Cannot create " + c.getName() + ": " + e.getMessage());          }      }      /**       * Returns a PropertyDescriptor[] for the given Class.       *       * @param c The Class to retrieve PropertyDescriptors for.       * @return A PropertyDescriptor[] describing the Class.       * @throws SQLException if introspection failed.       */      private PropertyDescriptor[] propertyDescriptors(Class c)          throws SQLException {          // Introspector caches BeanInfo classes for better performance          BeanInfo beanInfo = null;          try {              beanInfo = Introspector.getBeanInfo(c);          } catch (IntrospectionException e) {              throw new SQLException(                  "Bean introspection failed: " + e.getMessage());          }          return beanInfo.getPropertyDescriptors();      }      /**       * The positions in the returned array represent column numbers.  The        * values stored at each position represent the index in the        * <code>PropertyDescriptor[]</code> for the bean property that matches        * the column name.  If no bean property was found for a column, the        * position is set to <code>PROPERTY_NOT_FOUND</code>.       *        * @param rsmd The <code>ResultSetMetaData</code> containing column        * information.       *        * @param props The bean property descriptors.       *        * @throws SQLException if a database access error occurs       *       * @return An int[] with column index to property index mappings.  The 0th        * element is meaningless because JDBC column indexing starts at 1.       */      protected int[] mapColumnsToProperties(ResultSetMetaData rsmd,              PropertyDescriptor[] props) throws SQLException {          int cols = rsmd.getColumnCount();          int columnToProperty[] = new int[cols + 1];          Arrays.fill(columnToProperty, PROPERTY_NOT_FOUND);          for (int col = 1; col <= cols; col++) {              String columnName = rsmd.getColumnName(col);              for (int i = 0; i < props.length; i++) {                  if (columnName.equalsIgnoreCase(props[i].getName())) {                      columnToProperty[col] = i;                      break;                  }              }          }          return columnToProperty;      }      /**       * Convert a <code>ResultSet</code> column into an object.  Simple        * implementations could just call <code>rs.getObject(index)</code> while       * more complex implementations could perform type manipulation to match        * the column's type to the bean property type.       *        * <p>       * This implementation calls the appropriate <code>ResultSet</code> getter        * method for the given property type to perform the type conversion.  If        * the property type doesn't match one of the supported        * <code>ResultSet</code> types, <code>getObject</code> is called.       * </p>       *        * @param rs The <code>ResultSet</code> currently being processed.  It is       * positioned on a valid row before being passed into this method.       *        * @param index The current column index being processed.       *        * @param propType The bean property type that this column needs to be       * converted into.       *        * @throws SQLException if a database access error occurs       *        * @return The object from the <code>ResultSet</code> at the given column       * index after optional type processing or <code>null</code> if the column       * value was SQL NULL.       */      protected Object processColumn(ResultSet rs, int index, Class propType)          throws SQLException {          if ( !propType.isPrimitive() && rs.getObject(index) == null ) {              return null;          }          if (propType.equals(String.class)) {              return rs.getString(index);          } else if (              propType.equals(Integer.TYPE) || propType.equals(Integer.class)) {              return new Integer(rs.getInt(index));          } else if (              propType.equals(Boolean.TYPE) || propType.equals(Boolean.class)) {              return new Boolean(rs.getBoolean(index));          } else if (propType.equals(Long.TYPE) || propType.equals(Long.class)) {              return new Long(rs.getLong(index));          } else if (              propType.equals(Double.TYPE) || propType.equals(Double.class)) {              return new Double(rs.getDouble(index));          } else if (              propType.equals(Float.TYPE) || propType.equals(Float.class)) {              return new Float(rs.getFloat(index));          } else if (              propType.equals(Short.TYPE) || propType.equals(Short.class)) {              return new Short(rs.getShort(index));          } else if (propType.equals(Byte.TYPE) || propType.equals(Byte.class)) {              return new Byte(rs.getByte(index));          } else if (propType.equals(Timestamp.class)) {              return rs.getTimestamp(index);          } else {              return rs.getObject(index);          }      }  }