View Javadoc
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&lt;Object[]&gt;}.  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 }