1 56 package org.objectstyle.cayenne.access; 57 58 import java.io.IOException ; 59 import java.io.PrintWriter ; 60 import java.io.StringWriter ; 61 import java.sql.CallableStatement ; 62 import java.sql.Connection ; 63 import java.sql.ResultSet ; 64 import java.sql.SQLException ; 65 import java.sql.Statement ; 66 import java.util.ArrayList ; 67 import java.util.Collections ; 68 import java.util.HashMap ; 69 import java.util.List ; 70 import java.util.Map ; 71 72 import org.apache.log4j.Logger; 73 import org.objectstyle.cayenne.CayenneException; 74 import org.objectstyle.cayenne.DataRow; 75 import org.objectstyle.cayenne.access.types.ExtendedType; 76 import org.objectstyle.cayenne.map.DbEntity; 77 import org.objectstyle.cayenne.util.Util; 78 79 89 public class DefaultResultIterator implements ResultIterator { 90 private static Logger logObj = Logger.getLogger(DefaultResultIterator.class); 91 92 protected Connection connection; 94 protected Statement statement; 95 protected ResultSet resultSet; 96 97 protected org.objectstyle.cayenne.access.util.ResultDescriptor descriptor; 99 100 protected int mapCapacity; 101 102 protected boolean closingConnection; 103 protected boolean isClosed; 104 105 protected boolean nextRow; 106 protected int fetchedSoFar; 107 protected int fetchLimit; 108 109 113 public static Map readProcedureOutParameters( 114 CallableStatement statement, 115 org.objectstyle.cayenne.access.util.ResultDescriptor resultDescriptor) 116 throws SQLException , Exception { 117 118 int resultWidth = resultDescriptor.getResultWidth(); 119 if (resultWidth > 0) { 120 Map dataRow = new HashMap (resultWidth * 2, 0.75f); 121 ExtendedType[] converters = resultDescriptor.getConverters(); 122 int[] jdbcTypes = resultDescriptor.getJdbcTypes(); 123 String [] names = resultDescriptor.getNames(); 124 int[] outParamIndexes = resultDescriptor.getOutParamIndexes(); 125 126 for (int i = 0; i < outParamIndexes.length; i++) { 128 int index = outParamIndexes[i]; 129 130 Object val = 132 converters[index].materializeObject( 133 statement, 134 index + 1, 135 jdbcTypes[index]); 136 dataRow.put(names[index], val); 137 } 138 139 return dataRow; 140 } 141 142 return Collections.EMPTY_MAP; 143 } 144 145 public DefaultResultIterator( 146 Connection connection, 147 Statement statement, 148 ResultSet resultSet, 149 org.objectstyle.cayenne.access.util.ResultDescriptor descriptor, 150 int fetchLimit) 151 throws SQLException , CayenneException { 152 153 this.connection = connection; 154 this.statement = statement; 155 this.resultSet = resultSet; 156 this.descriptor = descriptor; 157 this.fetchLimit = fetchLimit; 158 159 this.mapCapacity = (int) Math.ceil((descriptor.getNames().length) / 0.75); 160 161 checkNextRow(); 162 } 163 164 168 protected void checkNextRow() throws SQLException , CayenneException { 169 nextRow = false; 170 if ((fetchLimit <= 0 || fetchedSoFar < fetchLimit) && resultSet.next()) { 171 nextRow = true; 172 fetchedSoFar++; 173 } 174 } 175 176 180 public boolean hasNextRow() { 181 return nextRow; 182 } 183 184 187 public Map nextDataRow() throws CayenneException { 188 if (!hasNextRow()) { 189 throw new CayenneException("An attempt to read uninitialized row or past the end of the iterator."); 190 } 191 192 try { 193 Map row = readDataRow(); 195 196 checkNextRow(); 198 199 return row; 200 } 201 catch (SQLException sqex) { 202 throw new CayenneException("Exception reading ResultSet.", sqex); 203 } 204 } 205 206 211 public int getDataRowWidth() { 212 return descriptor.getResultWidth(); 213 } 214 215 219 public List dataRows(boolean close) throws CayenneException { 220 List list = new ArrayList (); 221 222 try { 223 while (this.hasNextRow()) { 224 list.add(this.nextDataRow()); 225 } 226 return list; 227 } 228 finally { 229 if (close) { 230 this.close(); 231 } 232 } 233 } 234 235 239 protected Map readDataRow() throws SQLException , CayenneException { 240 try { 241 Map dataRow = new DataRow(mapCapacity); 242 ExtendedType[] converters = descriptor.getConverters(); 243 int[] jdbcTypes = descriptor.getJdbcTypes(); 244 String [] names = descriptor.getNames(); 245 int resultWidth = names.length; 246 247 for (int i = 0; i < resultWidth; i++) { 249 Object val = 251 converters[i].materializeObject(resultSet, i + 1, jdbcTypes[i]); 252 dataRow.put(names[i], val); 253 } 254 255 return dataRow; 256 } 257 catch (CayenneException cex) { 258 throw cex; 260 } 261 catch (Exception otherex) { 262 throw new CayenneException( 263 "Exception materializing column.", 264 Util.unwindException(otherex)); 265 } 266 } 267 268 273 protected Map readIdRow(DbEntity entity) throws SQLException , CayenneException { 274 try { 275 Map idRow = new DataRow(2); 276 ExtendedType[] converters = descriptor.getConverters(); 277 int[] jdbcTypes = descriptor.getJdbcTypes(); 278 String [] names = descriptor.getNames(); 279 int[] idIndex = descriptor.getIdIndexes(entity); 280 int len = idIndex.length; 281 282 for (int i = 0; i < len; i++) { 283 284 int index = idIndex[i]; 286 287 Object val = 289 converters[index].materializeObject( 290 resultSet, 291 index + 1, 292 jdbcTypes[index]); 293 idRow.put(names[index], val); 294 } 295 296 return idRow; 297 } 298 catch (CayenneException cex) { 299 throw cex; 301 } 302 catch (Exception otherex) { 303 logObj.warn("Error", otherex); 304 throw new CayenneException( 305 "Exception materializing id column.", 306 Util.unwindException(otherex)); 307 } 308 } 309 310 315 public void close() throws CayenneException { 316 if (!isClosed) { 317 318 nextRow = false; 319 320 StringWriter errors = new StringWriter (); 321 PrintWriter out = new PrintWriter (errors); 322 323 try { 324 resultSet.close(); 325 } 326 catch (SQLException e1) { 327 out.println("Error closing ResultSet"); 328 e1.printStackTrace(out); 329 } 330 331 if (statement != null) { 332 try { 333 statement.close(); 334 } 335 catch (SQLException e2) { 336 out.println("Error closing PreparedStatement"); 337 e2.printStackTrace(out); 338 } 339 } 340 341 if (connection != null && this.isClosingConnection()) { 344 try { 345 connection.close(); 346 } 347 catch (SQLException e3) { 348 out.println("Error closing Connection"); 349 e3.printStackTrace(out); 350 } 351 } 352 353 try { 354 out.close(); 355 errors.close(); 356 } 357 catch (IOException ioex) { 358 } 362 StringBuffer buf = errors.getBuffer(); 363 364 if (buf.length() > 0) { 365 throw new CayenneException("Error closing ResultIterator: " + buf); 366 } 367 368 isClosed = true; 369 } 370 } 371 372 377 public boolean isClosingConnection() { 378 return closingConnection; 379 } 380 381 384 public void setClosingConnection(boolean flag) { 385 this.closingConnection = flag; 386 } 387 388 391 public void skipDataRow() throws CayenneException { 392 if (!hasNextRow()) { 393 throw new CayenneException("An attempt to read uninitialized row or past the end of the iterator."); 394 } 395 396 try { 397 checkNextRow(); 398 } 399 catch (SQLException sqex) { 400 throw new CayenneException("Exception reading ResultSet.", sqex); 401 } 402 } 403 404 410 public Map nextObjectId(DbEntity entity) throws CayenneException { 411 if (!hasNextRow()) { 412 throw new CayenneException("An attempt to read uninitialized row or past the end of the iterator."); 413 } 414 415 try { 416 Map row = readIdRow(entity); 418 419 checkNextRow(); 421 422 return row; 423 } 424 catch (SQLException sqex) { 425 throw new CayenneException("Exception reading ResultSet.", sqex); 426 } 427 } 428 } 429 | Popular Tags |