/******************************************************************************* * Copyright (c) 2004, 2007 IBM Corporation and Cambridge Semantics Incorporated. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * File: $Source: /cvsroot/slrp/common/com.ibm.adtech.jdbc.utils/src/com/ibm/adtech/jdbc/utils/ResultSetIterator.java,v $ * Created by: Joe Betz * Created on: 9/30/2005 * Revision: $Id: ResultSetIterator.java 176 2007-07-31 14:22:30Z mroy $ * * Contributors: * IBM Corporation - initial API and implementation * Cambridge Semantics Incorporated - Fork to Anzo *******************************************************************************/ package org.openanzo.jdbc.utils; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.Iterator; import java.util.NoSuchElementException; import org.openanzo.exceptions.ExceptionConstants; import org.openanzo.exceptions.LogUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Implements iterator support over query result sets, which JDBC was lacking. By default each row in a result set is transformed to a Map where key is the * column name and object is the value. However, any iterator Transform may be supplied to instances of this class which will convert rows in a result set to * whatever Java type is most convenient. * * Example transforms are included. see: toMapTransform and toArrayTransform. * * @param <E> * type of object that iterator will return * * @author Joe Betz * */ public class ResultSetIterator<E> implements ClosableIterator<E> { private static final Logger log = LoggerFactory.getLogger(ResultSetIterator.class); private final ResultSet rs; private final PreparedStatement ps; private boolean checked = false; private boolean isClosed = false; private final Transformer<E> transformer; private boolean done = false; /** * Construct a new iterator over the results in the provided ResultSet. In addition to closing the ResultSet when this iterator is closed, the provided * PreparedStatement will be returned to the provided PreparedStatementCache. Also, the iterator transforms the rows of the result set using the supplied * transformer. * * @param rs * A JDBC ResultSet to iterate over. * @param ps * PreparedStatement to return to the given PreparedStatementCache when the iterator closes. * @param cache * A cache to return the given PreparedStatement to. * @param transformer * A Transformer for converting rows in the ResultSet to some type. * @throws UnhandledRdbException * {@link ExceptionConstants.RDB#FAILED_GETTING_RESULT} if there was an error getting the next result from the result set */ public ResultSetIterator(ResultSet rs, PreparedStatement ps, PreparedStatementProvider cache, Transformer<E> transformer) throws UnhandledRdbException { this.rs = rs; this.ps = ps; try { done = !rs.next(); checked = true; } catch (SQLException e) { throw new UnhandledRdbException(ExceptionConstants.RDB.FAILED_GETTING_RESULT, e); } this.transformer = transformer; } /** * @see java.util.Iterator#hasNext() */ public boolean hasNext() { if (isClosed) return false; try { if (checked) { return !done; } done = !rs.next(); if (done) { close(); } checked = true; return !done; } catch (SQLException e) { throw new UnhandledRdbException(ExceptionConstants.RDB.FAILED_GETTING_RESULT, e); } } /** * @see java.util.Iterator#next() */ public E next() { if (isClosed) throw new UnsupportedOperationException("Iterator already closed."); if (done) throw new NoSuchElementException(); if (!checked) { try { done = !rs.next(); if (done) { close(); throw new UnsupportedOperationException("Iterator already closed."); } } catch (SQLException e) { throw new UnhandledRdbException(ExceptionConstants.RDB.FAILED_GETTING_RESULT, e); } } checked = false; return transformer.transform(rs); } /** * @see java.util.Iterator#remove() */ public void remove() { throw new UnsupportedOperationException(); } /** * @see ClosableIterator#close() */ public void close() { if (isClosed) return; isClosed = true; try { rs.close(); } catch (SQLException e) { log.debug(LogUtils.RDB_MARKER, "Error closing result set", e); } try { if (ps != null) ps.close(); } catch (SQLException e) { throw new UnhandledRdbException(ExceptionConstants.RDB.FAILED_CLOSING_PREPAREDSTATEMENT, e); } } public Iterator<E> iterator() { return this; } }