1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 package org.apache.commons.dbutils; 18 19 import java.sql.ResultSet; 20 import java.sql.SQLException; 21 import java.util.Iterator; 22 23 /** 24 * <p> 25 * Wraps a {@code ResultSet} in an {@code Iterator<Object[]>}. This is useful 26 * when you want to present a non-database application layer with domain 27 * neutral data. 28 * </p> 29 * 30 * <p> 31 * This implementation requires the {@code ResultSet.isLast()} method 32 * to be implemented. 33 * </p> 34 */ 35 public class ResultSetIterator implements Iterator<Object[]> { 36 37 /** 38 * Generates an {@code Iterable}, suitable for use in for-each loops. 39 * 40 * @param resultSet Wrap this {@code ResultSet} in an {@code Iterator}. 41 * @return an {@code Iterable}, suitable for use in for-each loops. 42 */ 43 public static Iterable<Object[]> iterable(final ResultSet resultSet) { 44 return () -> new ResultSetIterator(resultSet); 45 } 46 47 /** 48 * The wrapped {@code ResultSet}. 49 */ 50 private final ResultSet resultSet; 51 52 /** 53 * The processor to use when converting a row into an Object[]. 54 */ 55 private final RowProcessor convert; 56 57 /** 58 * Constructor for ResultSetIterator. 59 * @param resultSet Wrap this {@code ResultSet} in an {@code Iterator}. 60 */ 61 public ResultSetIterator(final ResultSet resultSet) { 62 this(resultSet, new BasicRowProcessor()); 63 } 64 65 /** 66 * Constructor for ResultSetIterator. 67 * @param resultSet Wrap this {@code ResultSet} in an {@code Iterator}. 68 * @param convert The processor to use when converting a row into an 69 * {@code Object[]}. Defaults to a 70 * {@code BasicRowProcessor}. 71 */ 72 public ResultSetIterator(final ResultSet resultSet, final RowProcessor convert) { 73 this.resultSet = resultSet; 74 this.convert = convert; 75 } 76 77 /** 78 * Returns true if there are more rows in the ResultSet. 79 * @return boolean {@code true} if there are more rows 80 * @throws RuntimeException if an SQLException occurs. 81 */ 82 @Override 83 public boolean hasNext() { 84 try { 85 return !resultSet.isLast(); 86 } catch (final SQLException e) { 87 rethrow(e); 88 return false; 89 } 90 } 91 92 /** 93 * Returns the next row as an {@code Object[]}. 94 * @return An {@code Object[]} with the same number of elements as 95 * columns in the {@code ResultSet}. 96 * @see java.util.Iterator#next() 97 * @throws RuntimeException if an SQLException occurs. 98 */ 99 @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 }