1 56 package org.objectstyle.cayenne.access.jdbc; 57 58 import java.io.IOException ; 59 import java.io.PrintWriter ; 60 import java.io.StringWriter ; 61 import java.sql.Connection ; 62 import java.sql.ResultSet ; 63 import java.sql.SQLException ; 64 import java.sql.Statement ; 65 import java.util.ArrayList ; 66 import java.util.List ; 67 import java.util.Map ; 68 69 import org.objectstyle.cayenne.CayenneException; 70 import org.objectstyle.cayenne.CayenneRuntimeException; 71 import org.objectstyle.cayenne.DataRow; 72 import org.objectstyle.cayenne.access.ResultIterator; 73 import org.objectstyle.cayenne.access.types.ExtendedType; 74 import org.objectstyle.cayenne.map.DbAttribute; 75 import org.objectstyle.cayenne.map.DbEntity; 76 import org.objectstyle.cayenne.util.Util; 77 78 84 public class JDBCResultIterator implements ResultIterator { 86 87 protected Connection connection; 89 protected Statement statement; 90 protected ResultSet resultSet; 91 92 protected RowDescriptor rowDescriptor; 93 94 protected DbEntity rootEntity; 96 protected int[] pkIndices; 97 98 protected int mapCapacity; 99 100 protected boolean closingConnection; 101 protected boolean closed; 102 103 protected boolean nextRow; 104 protected int fetchedSoFar; 105 protected int fetchLimit; 106 107 110 public JDBCResultIterator(Connection connection, Statement statement, 111 ResultSet resultSet, RowDescriptor descriptor, int fetchLimit) 112 throws SQLException , CayenneException { 113 114 this.connection = connection; 115 this.statement = statement; 116 this.resultSet = resultSet; 117 this.rowDescriptor = descriptor; 118 this.fetchLimit = fetchLimit; 119 120 this.mapCapacity = (int) Math.ceil((descriptor.getWidth()) / 0.75); 121 122 checkNextRow(); 123 } 124 125 128 public List dataRows(boolean close) throws CayenneException { 129 List list = new ArrayList (); 130 131 try { 132 while (this.hasNextRow()) { 133 list.add(this.nextDataRow()); 134 } 135 } 136 finally { 137 if (close) { 138 this.close(); 139 } 140 } 141 142 return list; 143 } 144 145 149 public boolean hasNextRow() { 150 return nextRow; 151 } 152 153 156 public Map nextDataRow() throws CayenneException { 157 if (!hasNextRow()) { 158 throw new CayenneException( 159 "An attempt to read uninitialized row or past the end of the iterator."); 160 } 161 162 try { 163 Map row = readDataRow(); 165 166 checkNextRow(); 168 169 return row; 170 } 171 catch (SQLException sqex) { 172 throw new CayenneException("Exception reading ResultSet.", sqex); 173 } 174 } 175 176 180 public Map nextObjectId(DbEntity entity) 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 if (rootEntity != entity || pkIndices == null) { 188 this.rootEntity = entity; 189 indexPK(); 190 } 191 192 try { 193 Map row = readIdRow(); 197 198 checkNextRow(); 200 201 return row; 202 } 203 catch (SQLException sqex) { 204 throw new CayenneException("Exception reading ResultSet.", sqex); 205 } 206 } 207 208 public void skipDataRow() throws CayenneException { 209 if (!hasNextRow()) { 210 throw new CayenneException( 211 "An attempt to read uninitialized row or past the end of the iterator."); 212 } 213 214 try { 215 checkNextRow(); 216 } 217 catch (SQLException sqex) { 218 throw new CayenneException("Exception reading ResultSet.", sqex); 219 } 220 } 221 222 227 public void close() throws CayenneException { 228 if (!closed) { 229 230 nextRow = false; 231 232 StringWriter errors = new StringWriter (); 233 PrintWriter out = new PrintWriter (errors); 234 235 try { 236 resultSet.close(); 237 } 238 catch (SQLException e1) { 239 out.println("Error closing ResultSet"); 240 e1.printStackTrace(out); 241 } 242 243 if (statement != null) { 244 try { 245 statement.close(); 246 } 247 catch (SQLException e2) { 248 out.println("Error closing PreparedStatement"); 249 e2.printStackTrace(out); 250 } 251 } 252 253 if (connection != null && isClosingConnection()) { 256 try { 257 connection.close(); 258 } 259 catch (SQLException e3) { 260 out.println("Error closing Connection"); 261 e3.printStackTrace(out); 262 } 263 } 264 265 try { 266 out.close(); 267 errors.close(); 268 } 269 catch (IOException ioex) { 270 } 273 274 StringBuffer buf = errors.getBuffer(); 275 if (buf.length() > 0) { 276 throw new CayenneException("Error closing ResultIterator: " + buf); 277 } 278 279 closed = true; 280 } 281 } 282 283 286 public int getDataRowWidth() { 287 return rowDescriptor.getWidth(); 288 } 289 290 294 protected void checkNextRow() throws SQLException , CayenneException { 295 nextRow = false; 296 if ((fetchLimit <= 0 || fetchedSoFar < fetchLimit) && resultSet.next()) { 297 nextRow = true; 298 fetchedSoFar++; 299 } 300 } 301 302 305 protected Map readDataRow() throws SQLException , CayenneException { 306 try { 307 Map dataRow = new DataRow(mapCapacity); 308 ExtendedType[] converters = rowDescriptor.getConverters(); 309 ColumnDescriptor[] columns = rowDescriptor.getColumns(); 310 int resultWidth = rowDescriptor.getWidth(); 311 312 for (int i = 0; i < resultWidth; i++) { 314 Object val = converters[i].materializeObject(resultSet, i + 1, columns[i] 316 .getJdbcType()); 317 dataRow.put(columns[i].getLabel(), val); 318 } 319 320 return dataRow; 321 } 322 catch (CayenneException cex) { 323 throw cex; 325 } 326 catch (Exception otherex) { 327 throw new CayenneException("Exception materializing column.", Util 328 .unwindException(otherex)); 329 } 330 } 331 332 336 protected Map readIdRow() throws SQLException , CayenneException { 337 try { 338 Map idRow = new DataRow(2); 339 ExtendedType[] converters = rowDescriptor.getConverters(); 340 ColumnDescriptor[] columns = rowDescriptor.getColumns(); 341 int len = pkIndices.length; 342 343 for (int i = 0; i < len; i++) { 344 345 int index = pkIndices[i]; 347 348 Object val = converters[index].materializeObject(resultSet, 350 index + 1, 351 columns[index].getJdbcType()); 352 idRow.put(columns[index].getLabel(), val); 353 } 354 355 return idRow; 356 } 357 catch (CayenneException cex) { 358 throw cex; 360 } 361 catch (Exception otherex) { 362 throw new CayenneException("Exception materializing id column.", Util 363 .unwindException(otherex)); 364 } 365 } 366 367 370 protected void indexPK() { 371 if (rootEntity == null) { 372 throw new CayenneRuntimeException("Null root DbEntity, can't index PK"); 373 } 374 375 int len = rootEntity.getPrimaryKey().size(); 376 377 if (len == 0) { 379 throw new CayenneRuntimeException("Root DbEntity has no PK defined: " 380 + rootEntity); 381 } 382 383 int[] pk = new int[len]; 384 ColumnDescriptor[] columns = rowDescriptor.getColumns(); 385 for (int i = 0, j = 0; i < columns.length; i++) { 386 DbAttribute a = (DbAttribute) rootEntity.getAttribute(columns[i].getName()); 387 if (a != null && a.isPrimaryKey()) { 388 pk[j++] = i; 389 } 390 } 391 392 this.pkIndices = pk; 393 } 394 395 400 public boolean isClosingConnection() { 401 return closingConnection; 402 } 403 404 407 public void setClosingConnection(boolean flag) { 408 this.closingConnection = flag; 409 } 410 411 public RowDescriptor getRowDescriptor() { 412 return rowDescriptor; 413 } 414 } | Popular Tags |