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.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   * @param <K> The type of the key
49   * @see org.apache.commons.dbutils.ResultSetHandler
50   * @since DbUtils 1.1
51   */
52  public class KeyedHandler<K> extends AbstractKeyedHandler<K, Map<String, Object>> {
53  
54      /**
55       * The RowProcessor implementation to use when converting rows
56       * into Objects.
57       */
58      protected final RowProcessor convert;
59  
60      /**
61       * The column index to retrieve key values from.  Defaults to 1.
62       */
63      protected final int columnIndex;
64  
65      /**
66       * The column name to retrieve key values from.  Either columnName or
67       * columnIndex will be used but never both.
68       */
69      protected final String columnName;
70  
71      /**
72       * Creates a new instance of KeyedHandler.  The value of the first column
73       * of each row will be a key in the Map.
74       */
75      public KeyedHandler() {
76          this(ArrayHandler.ROW_PROCESSOR, 1, null);
77      }
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       * @param convert The <code>RowProcessor</code> implementation
84       * to use when converting rows into Maps
85       */
86      public KeyedHandler(RowProcessor convert) {
87          this(convert, 1, null);
88      }
89  
90      /**
91       * Creates a new instance of KeyedHandler.
92       *
93       * @param columnIndex The values to use as keys in the Map are
94       * retrieved from the column at this index.
95       */
96      public KeyedHandler(int columnIndex) {
97          this(ArrayHandler.ROW_PROCESSOR, columnIndex, null);
98      }
99  
100     /**
101      * Creates a new instance of KeyedHandler.
102      *
103      * @param columnName The values to use as keys in the Map are
104      * retrieved from the column with this name.
105      */
106     public KeyedHandler(String columnName) {
107         this(ArrayHandler.ROW_PROCESSOR, 1, columnName);
108     }
109 
110     /** Private Helper
111      * @param convert The <code>RowProcessor</code> implementation
112      * to use when converting rows into Maps
113      * @param columnIndex The values to use as keys in the Map are
114      * retrieved from the column at this index.
115      * @param columnName The values to use as keys in the Map are
116      * retrieved from the column with this name.
117      */
118     private KeyedHandler(RowProcessor convert, int columnIndex,
119             String columnName) {
120         super();
121         this.convert = convert;
122         this.columnIndex = columnIndex;
123         this.columnName = columnName;
124     }
125     /**
126      * This factory method is called by <code>handle()</code> to retrieve the
127      * key value from the current <code>ResultSet</code> row.  This
128      * implementation returns <code>ResultSet.getObject()</code> for the
129      * configured key column name or index.
130      * @param rs ResultSet to create a key from
131      * @return Object from the configured key column name/index
132      *
133      * @throws SQLException if a database access error occurs
134      * @throws ClassCastException if the class datatype does not match the column type
135      */
136     // We assume that the user has picked the correct type to match the column
137     // so getObject will return the appropriate type and the cast will succeed.
138     @SuppressWarnings("unchecked")
139     @Override
140     protected K createKey(ResultSet rs) throws SQLException {
141         return (columnName == null) ?
142                (K) rs.getObject(columnIndex) :
143                (K) rs.getObject(columnName);
144     }
145 
146     /**
147      * This factory method is called by <code>handle()</code> to store the
148      * current <code>ResultSet</code> row in some object. This
149      * implementation returns a <code>Map</code> with case insensitive column
150      * names as keys.  Calls to <code>map.get("COL")</code> and
151      * <code>map.get("col")</code> return the same value.
152      * @param rs ResultSet to create a row from
153      * @return Object typed Map containing column names to values
154      * @throws SQLException if a database access error occurs
155      */
156     @Override
157     protected Map<String, Object> createRow(ResultSet rs) throws SQLException {
158         return this.convert.toMap(rs);
159     }
160 
161 }