Coverage Report - org.apache.commons.beanutils.RowSetDynaClass
 
Classes in this File Line Coverage Branch Coverage Complexity
RowSetDynaClass
91%
31/34
90%
9/10
1.667
 
 1  
 /*
 2  
  * Licensed to the Apache Software Foundation (ASF) under one or more
 3  
  * contributor license agreements.  See the NOTICE file distributed with
 4  
  * this work for additional information regarding copyright ownership.
 5  
  * The ASF licenses this file to You under the Apache License, Version 2.0
 6  
  * (the "License"); you may not use this file except in compliance with
 7  
  * the License.  You may obtain a copy of the License at
 8  
  *
 9  
  *      http://www.apache.org/licenses/LICENSE-2.0
 10  
  *
 11  
  * Unless required by applicable law or agreed to in writing, software
 12  
  * distributed under the License is distributed on an "AS IS" BASIS,
 13  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 14  
  * See the License for the specific language governing permissions and
 15  
  * limitations under the License.
 16  
  */
 17  
 
 18  
 
 19  
 package org.apache.commons.beanutils;
 20  
 
 21  
 
 22  
 import java.io.Serializable;
 23  
 import java.sql.ResultSet;
 24  
 import java.sql.SQLException;
 25  
 import java.util.ArrayList;
 26  
 import java.util.List;
 27  
 
 28  
 
 29  
 /**
 30  
  * <p>Implementation of {@link DynaClass} that creates an in-memory collection
 31  
  * of {@link DynaBean}s representing the results of an SQL query.  Once the
 32  
  * {@link DynaClass} instance has been created, the JDBC <code>ResultSet</code>
 33  
  * and <code>Statement</code> on which it is based can be closed, and the
 34  
  * underlying <code>Connection</code> can be returned to its connection pool
 35  
  * (if you are using one).</p>
 36  
  *
 37  
  * <p>The normal usage pattern is something like:</p>
 38  
  * <pre>
 39  
  *   Connection conn = ...;  // Acquire connection from pool
 40  
  *   Statement stmt = conn.createStatement();
 41  
  *   ResultSet rs = stmt.executeQuery("SELECT ...");
 42  
  *   RowSetDynaClass rsdc = new RowSetDynaClass(rs);
 43  
  *   rs.close();
 44  
  *   stmt.close();
 45  
  *   ...;                    // Return connection to pool
 46  
  *   List rows = rsdc.getRows();
 47  
  *   ...;                   // Process the rows as desired
 48  
  * </pre>
 49  
  *
 50  
  * <p>Each column in the result set will be represented as a {@link DynaBean}
 51  
  * property of the corresponding name (optionally forced to lower case
 52  
  * for portability).  There will be one {@link DynaBean} in the
 53  
  * <code>List</code> returned by <code>getRows()</code> for each
 54  
  * row in the original <code>ResultSet</code>.</p>
 55  
  *
 56  
  * <p>In general, instances of {@link RowSetDynaClass} can be serialized
 57  
  * and deserialized, which will automatically include the list of
 58  
  * {@link DynaBean}s representing the data content.  The only exception
 59  
  * to this rule would be when the underlying property values that were
 60  
  * copied from the <code>ResultSet</code> originally cannot themselves
 61  
  * be serialized.  Therefore, a {@link RowSetDynaClass} makes a very
 62  
  * convenient mechanism for transporting data sets to remote Java-based
 63  
  * application components.</p>
 64  
  *
 65  
  * @author Craig R. McClanahan
 66  
  * @version $Revision: 926685 $ $Date: 2010-03-23 13:59:08 -0400 (Tue, 23 Mar 2010) $
 67  
  */
 68  
 
 69  1532
 public class RowSetDynaClass extends JDBCDynaClass implements DynaClass, Serializable {
 70  
 
 71  
 
 72  
     // ----------------------------------------------------- Instance variables
 73  
     
 74  
     /**
 75  
      * <p>Limits the size of the returned list.  The call to 
 76  
      * <code>getRows()</code> will return at most limit number of rows.
 77  
      * If less than or equal to 0, does not limit the size of the result.
 78  
      */
 79  12
     protected int limit = -1;
 80  
 
 81  
     /**
 82  
      * <p>The list of {@link DynaBean}s representing the contents of
 83  
      * the original <code>ResultSet</code> on which this
 84  
      * {@link RowSetDynaClass} was based.</p>
 85  
      */
 86  12
     protected List rows = new ArrayList();
 87  
 
 88  
     // ----------------------------------------------------------- Constructors
 89  
 
 90  
 
 91  
     /**
 92  
      * <p>Construct a new {@link RowSetDynaClass} for the specified
 93  
      * <code>ResultSet</code>.  The property names corresponding
 94  
      * to column names in the result set will be lower cased.</p>
 95  
      *
 96  
      * @param resultSet The result set to be wrapped
 97  
      *
 98  
      * @exception NullPointerException if <code>resultSet</code>
 99  
      *  is <code>null</code>
 100  
      * @exception SQLException if the metadata for this result set
 101  
      *  cannot be introspected
 102  
      */
 103  
     public RowSetDynaClass(ResultSet resultSet) throws SQLException {
 104  
 
 105  10
         this(resultSet, true, -1);
 106  
 
 107  10
     }
 108  
 
 109  
     /**
 110  
      * <p>Construct a new {@link RowSetDynaClass} for the specified
 111  
      * <code>ResultSet</code>.  The property names corresponding
 112  
      * to column names in the result set will be lower cased.</p>
 113  
      * 
 114  
      * If <code>limit</code> is not less than 0, max <code>limit</code>
 115  
      * number of rows will be copied into the list. 
 116  
      *
 117  
      * @param resultSet The result set to be wrapped
 118  
      * @param limit The maximum for the size of the result. 
 119  
      *
 120  
      * @exception NullPointerException if <code>resultSet</code>
 121  
      *  is <code>null</code>
 122  
      * @exception SQLException if the metadata for this result set
 123  
      *  cannot be introspected
 124  
      */
 125  
     public RowSetDynaClass(ResultSet resultSet, int limit) throws SQLException {
 126  
 
 127  1
         this(resultSet, true, limit);
 128  
 
 129  1
     }
 130  
 
 131  
 
 132  
     /**
 133  
      * <p>Construct a new {@link RowSetDynaClass} for the specified
 134  
      * <code>ResultSet</code>.  The property names corresponding
 135  
      * to the column names in the result set will be lower cased or not,
 136  
      * depending on the specified <code>lowerCase</code> value.</p>
 137  
      *
 138  
      * If <code>limit</code> is not less than 0, max <code>limit</code>
 139  
      * number of rows will be copied into the resultset. 
 140  
      *
 141  
      *
 142  
      * @param resultSet The result set to be wrapped
 143  
      * @param lowerCase Should property names be lower cased?
 144  
      *
 145  
      * @exception NullPointerException if <code>resultSet</code>
 146  
      *  is <code>null</code>
 147  
      * @exception SQLException if the metadata for this result set
 148  
      *  cannot be introspected
 149  
      */
 150  
     public RowSetDynaClass(ResultSet resultSet, boolean lowerCase)
 151  
                                                     throws SQLException {
 152  1
         this(resultSet, lowerCase, -1);
 153  
 
 154  1
     }
 155  
 
 156  
     /**
 157  
      * <p>Construct a new {@link RowSetDynaClass} for the specified
 158  
      * <code>ResultSet</code>.  The property names corresponding
 159  
      * to the column names in the result set will be lower cased or not,
 160  
      * depending on the specified <code>lowerCase</code> value.</p>
 161  
      *
 162  
      * <p><strong>WARNING</strong> - If you specify <code>false</code>
 163  
      * for <code>lowerCase</code>, the returned property names will
 164  
      * exactly match the column names returned by your JDBC driver.
 165  
      * Because different drivers might return column names in different
 166  
      * cases, the property names seen by your application will vary
 167  
      * depending on which JDBC driver you are using.</p>
 168  
      *
 169  
      * @param resultSet The result set to be wrapped
 170  
      * @param lowerCase Should property names be lower cased?
 171  
      * @param limit Maximum limit for the <code>List</code> of {@link DynaBean}
 172  
      *
 173  
      * @exception NullPointerException if <code>resultSet</code>
 174  
      *  is <code>null</code>
 175  
      * @exception SQLException if the metadata for this result set
 176  
      *  cannot be introspected
 177  
      */
 178  
     public RowSetDynaClass(ResultSet resultSet, boolean lowerCase, int limit)
 179  
                                                             throws SQLException {
 180  
 
 181  12
         this(resultSet, lowerCase, limit, false);
 182  
 
 183  12
     }
 184  
 
 185  
     /**
 186  
      * <p>Construct a new {@link RowSetDynaClass} for the specified
 187  
      * <code>ResultSet</code>.  The property names corresponding
 188  
      * to the column names in the result set will be lower cased or not,
 189  
      * depending on the specified <code>lowerCase</code> value.</p>
 190  
      *
 191  
      * <p><strong>WARNING</strong> - If you specify <code>false</code>
 192  
      * for <code>lowerCase</code>, the returned property names will
 193  
      * exactly match the column names returned by your JDBC driver.
 194  
      * Because different drivers might return column names in different
 195  
      * cases, the property names seen by your application will vary
 196  
      * depending on which JDBC driver you are using.</p>
 197  
      *
 198  
      * @param resultSet The result set to be wrapped
 199  
      * @param lowerCase Should property names be lower cased?
 200  
      * @param useColumnLabel true if the column label should be used, otherwise false
 201  
      *
 202  
      * @exception NullPointerException if <code>resultSet</code>
 203  
      *  is <code>null</code>
 204  
      * @exception SQLException if the metadata for this result set
 205  
      *  cannot be introspected
 206  
      * @since 1.8.3
 207  
      */
 208  
     public RowSetDynaClass(ResultSet resultSet, boolean lowerCase, boolean useColumnLabel)
 209  
         throws SQLException {
 210  0
         this(resultSet, lowerCase, -1, useColumnLabel);
 211  
 
 212  0
     }
 213  
 
 214  
     /**
 215  
      * <p>Construct a new {@link RowSetDynaClass} for the specified
 216  
      * <code>ResultSet</code>.  The property names corresponding
 217  
      * to the column names in the result set will be lower cased or not,
 218  
      * depending on the specified <code>lowerCase</code> value.</p>
 219  
      *
 220  
      * <p><strong>WARNING</strong> - If you specify <code>false</code>
 221  
      * for <code>lowerCase</code>, the returned property names will
 222  
      * exactly match the column names returned by your JDBC driver.
 223  
      * Because different drivers might return column names in different
 224  
      * cases, the property names seen by your application will vary
 225  
      * depending on which JDBC driver you are using.</p>
 226  
      *
 227  
      * @param resultSet The result set to be wrapped
 228  
      * @param lowerCase Should property names be lower cased?
 229  
      * @param limit Maximum limit for the <code>List</code> of {@link DynaBean}
 230  
      * @param useColumnLabel true if the column label should be used, otherwise false
 231  
      *
 232  
      * @exception NullPointerException if <code>resultSet</code>
 233  
      *  is <code>null</code>
 234  
      * @exception SQLException if the metadata for this result set
 235  
      *  cannot be introspected
 236  
      * @since 1.8.3
 237  
      */
 238  
     public RowSetDynaClass(ResultSet resultSet, boolean lowerCase, int limit, boolean useColumnLabel)
 239  12
                                                             throws SQLException {
 240  
 
 241  12
         if (resultSet == null) {
 242  0
             throw new NullPointerException();
 243  
         }
 244  12
         this.lowerCase = lowerCase;
 245  12
         this.limit = limit;
 246  12
         setUseColumnLabel(useColumnLabel);
 247  12
         introspect(resultSet);
 248  12
         copy(resultSet);
 249  
 
 250  12
     }
 251  
 
 252  
     /**
 253  
      * <p>Return a <code>List</code> containing the {@link DynaBean}s that
 254  
      * represent the contents of each <code>Row</code> from the
 255  
      * <code>ResultSet</code> that was the basis of this
 256  
      * {@link RowSetDynaClass} instance.  These {@link DynaBean}s are
 257  
      * disconnected from the database itself, so there is no problem with
 258  
      * modifying the contents of the list, or the values of the properties
 259  
      * of these {@link DynaBean}s.  However, it is the application's
 260  
      * responsibility to persist any such changes back to the database,
 261  
      * if it so desires.</p>
 262  
      *
 263  
      * @return A <code>List</code> of {@link DynaBean} instances
 264  
      */
 265  
     public List getRows() {
 266  
 
 267  5
         return (this.rows);
 268  
 
 269  
     }
 270  
 
 271  
 
 272  
     // ------------------------------------------------------ Protected Methods
 273  
 
 274  
 
 275  
     /**
 276  
      * <p>Copy the column values for each row in the specified
 277  
      * <code>ResultSet</code> into a newly created {@link DynaBean}, and add
 278  
      * this bean to the list of {@link DynaBean}s that will later by
 279  
      * returned by a call to <code>getRows()</code>.</p>
 280  
      *
 281  
      * @param resultSet The <code>ResultSet</code> whose data is to be
 282  
      *  copied
 283  
      *
 284  
      * @exception SQLException if an error is encountered copying the data
 285  
      */
 286  
     protected void copy(ResultSet resultSet) throws SQLException {
 287  
 
 288  12
         int cnt = 0;
 289  70
         while (resultSet.next() && (limit < 0  || cnt++ < limit) ) {
 290  58
             DynaBean bean = createDynaBean();
 291  812
             for (int i = 0; i < properties.length; i++) {
 292  754
                 String name = properties[i].getName();
 293  754
                 Object value = getObject(resultSet, name);
 294  754
                 bean.set(name, value);
 295  
             }
 296  58
             rows.add(bean);
 297  58
         }
 298  
 
 299  12
     }
 300  
 
 301  
 
 302  
     /**
 303  
      * <p>Create and return a new {@link DynaBean} instance to be used for
 304  
      * representing a row in the underlying result set.</p>
 305  
      *
 306  
      * @return A new <code>DynaBean</code> instance
 307  
      */
 308  
     protected DynaBean createDynaBean() {
 309  
 
 310  58
         return (new BasicDynaBean(this));
 311  
 
 312  
     }
 313  
 
 314  
 
 315  
 }