001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.commons.dbutils; 018 019import java.sql.ResultSet; 020import java.sql.SQLException; 021import java.util.Iterator; 022 023/** 024 * <p> 025 * Wraps a {@code ResultSet} in an {@code Iterator<Object[]>}. This is useful 026 * when you want to present a non-database application layer with domain 027 * neutral data. 028 * </p> 029 * 030 * <p> 031 * This implementation requires the {@code ResultSet.isLast()} method 032 * to be implemented. 033 * </p> 034 */ 035public class ResultSetIterator implements Iterator<Object[]> { 036 037 /** 038 * Generates an {@code Iterable}, suitable for use in for-each loops. 039 * 040 * @param resultSet Wrap this {@code ResultSet} in an {@code Iterator}. 041 * @return an {@code Iterable}, suitable for use in for-each loops. 042 */ 043 public static Iterable<Object[]> iterable(final ResultSet resultSet) { 044 return () -> new ResultSetIterator(resultSet); 045 } 046 047 /** 048 * The wrapped {@code ResultSet}. 049 */ 050 private final ResultSet resultSet; 051 052 /** 053 * The processor to use when converting a row into an Object[]. 054 */ 055 private final RowProcessor convert; 056 057 /** 058 * Constructor for ResultSetIterator. 059 * @param resultSet Wrap this {@code ResultSet} in an {@code Iterator}. 060 */ 061 public ResultSetIterator(final ResultSet resultSet) { 062 this(resultSet, new BasicRowProcessor()); 063 } 064 065 /** 066 * Constructor for ResultSetIterator. 067 * @param resultSet Wrap this {@code ResultSet} in an {@code Iterator}. 068 * @param convert The processor to use when converting a row into an 069 * {@code Object[]}. Defaults to a 070 * {@code BasicRowProcessor}. 071 */ 072 public ResultSetIterator(final ResultSet resultSet, final RowProcessor convert) { 073 this.resultSet = resultSet; 074 this.convert = convert; 075 } 076 077 /** 078 * Returns true if there are more rows in the ResultSet. 079 * @return boolean {@code true} if there are more rows 080 * @throws RuntimeException if an SQLException occurs. 081 */ 082 @Override 083 public boolean hasNext() { 084 try { 085 return !resultSet.isLast(); 086 } catch (final SQLException e) { 087 rethrow(e); 088 return false; 089 } 090 } 091 092 /** 093 * Returns the next row as an {@code Object[]}. 094 * @return An {@code Object[]} with the same number of elements as 095 * columns in the {@code ResultSet}. 096 * @see java.util.Iterator#next() 097 * @throws RuntimeException if an SQLException occurs. 098 */ 099 @Override 100 public Object[] next() { 101 try { 102 resultSet.next(); 103 return this.convert.toArray(resultSet); 104 } catch (final SQLException e) { 105 rethrow(e); 106 return null; 107 } 108 } 109 110 /** 111 * Deletes the current row from the {@code ResultSet}. 112 * @see java.util.Iterator#remove() 113 * @throws RuntimeException if an SQLException occurs. 114 */ 115 @Override 116 public void remove() { 117 try { 118 this.resultSet.deleteRow(); 119 } catch (final SQLException e) { 120 rethrow(e); 121 } 122 } 123 124 /** 125 * Rethrow the SQLException as a RuntimeException. This implementation 126 * creates a new RuntimeException with the SQLException's error message. 127 * @param e SQLException to rethrow 128 * @since 1.1 129 */ 130 protected void rethrow(final SQLException e) { 131 throw new RuntimeException(e.getMessage()); 132 } 133 134}