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 */
017 package org.apache.commons.dbutils.handlers;
018
019 import java.sql.ResultSet;
020 import java.sql.SQLException;
021 import java.util.Map;
022
023 import org.apache.commons.dbutils.RowProcessor;
024
025 /**
026 * <p>
027 * <code>ResultSetHandler</code> implementation that returns a Map of Maps.
028 * <code>ResultSet</code> rows are converted into Maps which are then stored
029 * in a Map under the given key.
030 * </p>
031 * <p>
032 * If you had a Person table with a primary key column called ID, you could
033 * retrieve rows from the table like this:
034 * <pre>
035 * ResultSetHandler h = new KeyedHandler("id");
036 * Map found = (Map) queryRunner.query("select id, name, age from person", h);
037 * Map jane = (Map) found.get(new Long(1)); // jane's id is 1
038 * String janesName = (String) jane.get("name");
039 * Integer janesAge = (Integer) jane.get("age");
040 * </pre>
041 * Note that the "id" passed to KeyedHandler and "name" and "age" passed to the
042 * returned Map's get() method can be in any case. The data types returned for
043 * name and age are dependent upon how your JDBC driver converts SQL column
044 * types from the Person table into Java types.
045 * </p>
046 * <p>This class is thread safe.</p>
047 *
048 * @see org.apache.commons.dbutils.ResultSetHandler
049 * @since DbUtils 1.1
050 */
051 public class KeyedHandler extends AbstractKeyedHandler<Object, Map<String, Object>> {
052
053 /**
054 * The RowProcessor implementation to use when converting rows
055 * into Objects.
056 */
057 protected final RowProcessor convert;
058
059 /**
060 * The column index to retrieve key values from. Defaults to 1.
061 */
062 protected final int columnIndex;
063
064 /**
065 * The column name to retrieve key values from. Either columnName or
066 * columnIndex will be used but never both.
067 */
068 protected final String columnName;
069
070 /**
071 * Creates a new instance of KeyedHandler. The value of the first column
072 * of each row will be a key in the Map.
073 */
074 public KeyedHandler() {
075 this(ArrayHandler.ROW_PROCESSOR, 1, null);
076 }
077
078 /**
079 * Creates a new instance of KeyedHandler. The value of the first column
080 * of each row will be a key in the Map.
081 *
082 * @param convert The <code>RowProcessor</code> implementation
083 * to use when converting rows into Maps
084 */
085 public KeyedHandler(RowProcessor convert) {
086 this(convert, 1, null);
087 }
088
089 /**
090 * Creates a new instance of KeyedHandler.
091 *
092 * @param columnIndex The values to use as keys in the Map are
093 * retrieved from the column at this index.
094 */
095 public KeyedHandler(int columnIndex) {
096 this(ArrayHandler.ROW_PROCESSOR, columnIndex, null);
097 }
098
099 /**
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 }