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