1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.dbutils.handlers;
18
19 import java.sql.ResultSet;
20 import java.sql.SQLException;
21 import java.util.HashMap;
22 import java.util.Map;
23
24 import org.apache.commons.dbutils.ResultSetHandler;
25 import org.apache.commons.dbutils.RowProcessor;
26
27 /**
28 * <p>
29 * <code>ResultSetHandler</code> implementation that returns a Map of Maps.
30 * <code>ResultSet</code> rows are converted into Maps which are then stored
31 * in a Map under the given key. Although this implementation uses Maps to
32 * store row contents, subclasses are encouraged to override the
33 * <code>createRow()</code> method to convert the rows into any kind of object.
34 * </p>
35 * <p>
36 * If you had a Person table with a primary key column called ID, you could
37 * retrieve rows from the table like this:
38 * <pre>
39 * ResultSetHandler h = new KeyedHandler("id");
40 * Map found = (Map) queryRunner.query("select id, name, age from person", h);
41 * Map jane = (Map) found.get(new Long(1)); // jane's id is 1
42 * String janesName = (String) jane.get("name");
43 * Integer janesAge = (Integer) jane.get("age");
44 * </pre>
45 * Note that the "id" passed to KeyedHandler and "name" and "age" passed to the
46 * returned Map's get() method can be in any case. The data types returned for
47 * name and age are dependent upon how your JDBC driver converts SQL column
48 * types from the Person table into Java types.
49 * </p>
50 * <p>
51 * To avoid these type issues you could subclass KeyedHandler and override
52 * <code>createRow()</code> to store rows in Java bean instances (ie. a
53 * Person class).
54 * </p>
55 * <p>This class is thread safe.</p>
56 *
57 * @see org.apache.commons.dbutils.ResultSetHandler
58 * @since DbUtils 1.1
59 */
60 public class KeyedHandler implements ResultSetHandler {
61
62 /**
63 * The RowProcessor implementation to use when converting rows
64 * into Objects.
65 */
66 protected RowProcessor convert = ArrayHandler.ROW_PROCESSOR;
67
68 /**
69 * The column index to retrieve key values from. Defaults to 1.
70 */
71 protected int columnIndex = 1;
72
73 /**
74 * The column name to retrieve key values from. Either columnName or
75 * columnIndex will be used but never both.
76 */
77 protected String columnName = null;
78
79 /**
80 * Creates a new instance of KeyedHandler. The value of the first column
81 * of each row will be a key in the Map.
82 */
83 public KeyedHandler() {
84 super();
85 }
86
87 /**
88 * Creates a new instance of KeyedHandler. The value of the first column
89 * of each row will be a key in the Map.
90 *
91 * @param convert The <code>RowProcessor</code> implementation
92 * to use when converting rows into Maps
93 */
94 public KeyedHandler(RowProcessor convert) {
95 super();
96 this.convert = convert;
97 }
98
99 /**
100 * Creates a new instance of KeyedHandler.
101 *
102 * @param columnIndex The values to use as keys in the Map are
103 * retrieved from the column at this index.
104 */
105 public KeyedHandler(int columnIndex) {
106 super();
107 this.columnIndex = columnIndex;
108 }
109
110 /**
111 * Creates a new instance of KeyedHandler.
112 *
113 * @param columnName The values to use as keys in the Map are
114 * retrieved from the column with this name.
115 */
116 public KeyedHandler(String columnName) {
117 super();
118 this.columnName = columnName;
119 }
120
121 /**
122 * Convert each row's columns into a Map and store then
123 * in a <code>Map</code> under <code>ResultSet.getObject(key)</code> key.
124 *
125 * @return A <code>Map</code> of Maps, never <code>null</code>.
126 * @throws SQLException if a database access error occurs
127 * @see org.apache.commons.dbutils.ResultSetHandler#handle(java.sql.ResultSet)
128 */
129 public Object handle(ResultSet rs) throws SQLException {
130 Map result = createMap();
131 while (rs.next()) {
132 result.put(createKey(rs), createRow(rs));
133 }
134 return result;
135 }
136
137 /**
138 * This factory method is called by <code>handle()</code> to create the Map
139 * to store records in. This implementation returns a <code>HashMap</code>
140 * instance.
141 *
142 * @return Map to store records in
143 */
144 protected Map createMap() {
145 return new HashMap();
146 }
147
148 /**
149 * This factory method is called by <code>handle()</code> to retrieve the
150 * key value from the current <code>ResultSet</code> row. This
151 * implementation returns <code>ResultSet.getObject()</code> for the
152 * configured key column name or index.
153 * @param rs ResultSet to create a key from
154 * @return Object from the configured key column name/index
155 * @throws SQLException if a database access error occurs
156 */
157 protected Object createKey(ResultSet rs) throws SQLException {
158 return (columnName == null) ? rs.getObject(columnIndex) : rs
159 .getObject(columnName);
160 }
161
162 /**
163 * This factory method is called by <code>handle()</code> to store the
164 * current <code>ResultSet</code> row in some object. This
165 * implementation returns a <code>Map</code> with case insensitive column
166 * names as keys. Calls to <code>map.get("COL")</code> and
167 * <code>map.get("col")</code> return the same value.
168 * @param rs ResultSet to create a row from
169 * @return Object typed Map containing column names to values
170 * @throws SQLException if a database access error occurs
171 */
172 protected Object createRow(ResultSet rs) throws SQLException {
173 return this.convert.toMap(rs);
174 }
175
176 }