1 19 20 package org.apache.cayenne.access.jdbc; 21 22 import java.io.IOException ; 23 import java.io.PrintWriter ; 24 import java.io.StringWriter ; 25 import java.sql.Connection ; 26 import java.sql.ResultSet ; 27 import java.sql.SQLException ; 28 import java.sql.Statement ; 29 import java.util.ArrayList ; 30 import java.util.List ; 31 import java.util.Map ; 32 33 import org.apache.cayenne.CayenneException; 34 import org.apache.cayenne.CayenneRuntimeException; 35 import org.apache.cayenne.DataRow; 36 import org.apache.cayenne.access.ResultIterator; 37 import org.apache.cayenne.access.types.ExtendedType; 38 import org.apache.cayenne.map.DbAttribute; 39 import org.apache.cayenne.map.DbEntity; 40 import org.apache.cayenne.util.Util; 41 42 48 public class JDBCResultIterator implements ResultIterator { 50 51 protected Connection connection; 53 protected Statement statement; 54 protected ResultSet resultSet; 55 56 protected RowDescriptor rowDescriptor; 57 58 DataRowPostProcessor postProcessor; 59 60 protected DbEntity rootEntity; 62 protected int[] pkIndices; 63 64 protected int mapCapacity; 65 66 protected boolean closingConnection; 67 protected boolean closed; 68 69 protected boolean nextRow; 70 protected int fetchedSoFar; 71 protected int fetchLimit; 72 73 private String [] labels; 74 private int[] types; 75 76 79 public JDBCResultIterator(Connection connection, Statement statement, 80 ResultSet resultSet, RowDescriptor descriptor, int fetchLimit) 81 throws CayenneException { 82 83 this.connection = connection; 84 this.statement = statement; 85 this.resultSet = resultSet; 86 this.rowDescriptor = descriptor; 87 this.fetchLimit = fetchLimit; 88 89 this.mapCapacity = (int) Math.ceil((descriptor.getWidth()) / 0.75); 90 91 checkNextRow(); 92 93 if(nextRow) { 94 ColumnDescriptor[] columns = descriptor.getColumns(); 96 int width = columns.length; 97 labels = new String [width]; 98 types = new int[width]; 99 100 for(int i = 0; i < width; i++) { 101 labels[i] = columns[i].getLabel(); 102 types[i] = columns[i].getJdbcType(); 103 } 104 } 105 } 106 107 110 public List dataRows(boolean close) throws CayenneException { 111 List list = new ArrayList (); 112 113 try { 114 while (this.hasNextRow()) { 115 list.add(this.nextDataRow()); 116 } 117 } 118 finally { 119 if (close) { 120 this.close(); 121 } 122 } 123 124 return list; 125 } 126 127 131 public boolean hasNextRow() { 132 return nextRow; 133 } 134 135 138 public Map nextDataRow() throws CayenneException { 139 if (!hasNextRow()) { 140 throw new CayenneException( 141 "An attempt to read uninitialized row or past the end of the iterator."); 142 } 143 144 Map row = readDataRow(); 146 147 checkNextRow(); 149 150 return row; 151 } 152 153 157 public Map nextObjectId(DbEntity entity) throws CayenneException { 158 if (!hasNextRow()) { 159 throw new CayenneException( 160 "An attempt to read uninitialized row or past the end of the iterator."); 161 } 162 163 if (rootEntity != entity || pkIndices == null) { 165 this.rootEntity = entity; 166 indexPK(); 167 } 168 169 Map row = readIdRow(); 173 174 checkNextRow(); 176 177 return row; 178 } 179 180 public void skipDataRow() throws CayenneException { 181 if (!hasNextRow()) { 182 throw new CayenneException( 183 "An attempt to read uninitialized row or past the end of the iterator."); 184 } 185 186 checkNextRow(); 187 } 188 189 194 public void close() throws CayenneException { 195 if (!closed) { 196 197 nextRow = false; 198 199 StringWriter errors = new StringWriter (); 200 PrintWriter out = new PrintWriter (errors); 201 202 try { 203 resultSet.close(); 204 } 205 catch (SQLException e1) { 206 out.println("Error closing ResultSet"); 207 e1.printStackTrace(out); 208 } 209 210 if (statement != null) { 211 try { 212 statement.close(); 213 } 214 catch (SQLException e2) { 215 out.println("Error closing PreparedStatement"); 216 e2.printStackTrace(out); 217 } 218 } 219 220 224 if (connection != null && isClosingConnection()) { 227 try { 228 connection.close(); 229 } 230 catch (SQLException e3) { 231 out.println("Error closing Connection"); 232 e3.printStackTrace(out); 233 } 234 } 235 236 try { 237 out.close(); 238 errors.close(); 239 } 240 catch (IOException ioex) { 241 } 244 245 StringBuffer buf = errors.getBuffer(); 246 if (buf.length() > 0) { 247 throw new CayenneException("Error closing ResultIterator: " + buf); 248 } 249 250 closed = true; 251 } 252 } 253 254 257 public int getDataRowWidth() { 258 return rowDescriptor.getWidth(); 259 } 260 261 265 protected void checkNextRow() throws CayenneException { 266 nextRow = false; 267 try { 268 if ((fetchLimit <= 0 || fetchedSoFar < fetchLimit) && resultSet.next()) { 269 nextRow = true; 270 fetchedSoFar++; 271 } 272 } 273 catch (SQLException e) { 274 throw new CayenneException("Error rewinding ResultSet", e); 275 } 276 } 277 278 281 protected Map readDataRow() throws CayenneException { 282 try { 283 DataRow dataRow = new DataRow(mapCapacity); 284 ExtendedType[] converters = rowDescriptor.getConverters(); 285 286 int resultWidth = labels.length; 287 288 for (int i = 0; i < resultWidth; i++) { 290 Object val = converters[i].materializeObject(resultSet, i + 1, types[i]); 292 dataRow.put(labels[i], val); 293 } 294 295 if (postProcessor != null) { 296 postProcessor.postprocessRow(resultSet, dataRow); 297 } 298 299 return dataRow; 300 } 301 catch (CayenneException cex) { 302 throw cex; 304 } 305 catch (Exception otherex) { 306 throw new CayenneException("Exception materializing column.", Util 307 .unwindException(otherex)); 308 } 309 } 310 311 315 protected Map readIdRow() throws CayenneException { 316 try { 317 DataRow idRow = new DataRow(2); 318 ExtendedType[] converters = rowDescriptor.getConverters(); 319 int len = pkIndices.length; 320 321 for (int i = 0; i < len; i++) { 322 323 int index = pkIndices[i]; 325 326 Object val = converters[index].materializeObject( 328 resultSet, 329 index + 1, 330 types[index]); 331 idRow.put(labels[index], val); 332 } 333 334 if (postProcessor != null) { 335 postProcessor.postprocessRow(resultSet, idRow); 336 } 337 338 return idRow; 339 } 340 catch (CayenneException cex) { 341 throw cex; 343 } 344 catch (Exception otherex) { 345 throw new CayenneException("Exception materializing id column.", Util 346 .unwindException(otherex)); 347 } 348 } 349 350 353 protected void indexPK() { 354 if (rootEntity == null) { 355 throw new CayenneRuntimeException("Null root DbEntity, can't index PK"); 356 } 357 358 int len = rootEntity.getPrimaryKey().size(); 359 360 if (len == 0) { 362 throw new CayenneRuntimeException("Root DbEntity has no PK defined: " 363 + rootEntity); 364 } 365 366 int[] pk = new int[len]; 367 ColumnDescriptor[] columns = rowDescriptor.getColumns(); 368 for (int i = 0, j = 0; i < columns.length; i++) { 369 DbAttribute a = (DbAttribute) rootEntity.getAttribute(columns[i].getName()); 370 if (a != null && a.isPrimaryKey()) { 371 pk[j++] = i; 372 } 373 } 374 375 this.pkIndices = pk; 376 } 377 378 383 public boolean isClosingConnection() { 384 return closingConnection; 385 } 386 387 390 public void setClosingConnection(boolean flag) { 391 this.closingConnection = flag; 392 } 393 394 public RowDescriptor getRowDescriptor() { 395 return rowDescriptor; 396 } 397 398 void setPostProcessor(DataRowPostProcessor postProcessor) { 399 this.postProcessor = postProcessor; 400 } 401 } 402 | Popular Tags |