| Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
| RowSetDynaClass |
|
| 1.6666666666666667;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 | } |